jusi-sql 0.2.0__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.
- jusi_sql-0.2.0/LICENSE +21 -0
- jusi_sql-0.2.0/PKG-INFO +175 -0
- jusi_sql-0.2.0/README.md +139 -0
- jusi_sql-0.2.0/pyproject.toml +33 -0
- jusi_sql-0.2.0/src/jusi_sql/__init__.py +63 -0
- jusi_sql-0.2.0/src/jusi_sql/catalog.py +55 -0
- jusi_sql-0.2.0/src/jusi_sql/completion.py +303 -0
- jusi_sql-0.2.0/src/jusi_sql/config.py +139 -0
- jusi_sql-0.2.0/src/jusi_sql/kernel.py +138 -0
- jusi_sql-0.2.0/src/jusi_sql/metadata.py +143 -0
- jusi_sql-0.2.0/src/jusi_sql/visidata.py +109 -0
- jusi_sql-0.2.0/src/jusi_sql/worker.py +125 -0
- jusi_sql-0.2.0/tests/test_catalog_config.py +89 -0
- jusi_sql-0.2.0/tests/test_completion.py +66 -0
- jusi_sql-0.2.0/tests/test_kernel.py +104 -0
- jusi_sql-0.2.0/tests/test_metadata_worker.py +85 -0
- jusi_sql-0.2.0/tests/test_visidata.py +62 -0
jusi_sql-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 notawhaleble
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
jusi_sql-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: jusi-sql
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: The SQL plugin-family contract and reusable provider toolkit for Jusi 1.0
|
|
5
|
+
Author: Jusi contributors
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 notawhaleble
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Python: >=3.9
|
|
29
|
+
Requires-Dist: jusi<2,>=1.0
|
|
30
|
+
Requires-Dist: sqlparse<0.6,>=0.5
|
|
31
|
+
Provides-Extra: test
|
|
32
|
+
Requires-Dist: pytest<9,>=8; extra == 'test'
|
|
33
|
+
Provides-Extra: visidata
|
|
34
|
+
Requires-Dist: visidata<4,>=3; extra == 'visidata'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# jusi-sql
|
|
38
|
+
|
|
39
|
+
`jusi-sql` is the independently installable SQL plugin family for Jusi 1.0.
|
|
40
|
+
It owns the user-facing `%%sql` contract and the provider-neutral code that
|
|
41
|
+
SQLite, PostgreSQL, ClickHouse, and future database plugins should share. It is
|
|
42
|
+
not an exact provider and therefore publishes no `jusi.plugins.v1` entry point.
|
|
43
|
+
|
|
44
|
+
## Family contract
|
|
45
|
+
|
|
46
|
+
Every exact SQL provider advertises the same catalog claim:
|
|
47
|
+
|
|
48
|
+
- family `sql`, magic `sql`
|
|
49
|
+
- capabilities `execute`, `followup`, `complete`, `interrupt`, and
|
|
50
|
+
`editor_actions`
|
|
51
|
+
- shared `sql` syntax and indentation profiles
|
|
52
|
+
- terminal-interactive presentation
|
|
53
|
+
|
|
54
|
+
An exact provider may refine syntax after handoff (for example `pgsql` or
|
|
55
|
+
`clickhouse`), but may not change the shared capabilities or presentation.
|
|
56
|
+
Providers own connections, transactions, dialect metadata queries,
|
|
57
|
+
cancellation, result rendering, selection meaning, and application IPC.
|
|
58
|
+
|
|
59
|
+
The family owns target configuration and selection, deterministic ownership of
|
|
60
|
+
one `%%sql` magic, the initial handoff payload, continuing-operation parsing,
|
|
61
|
+
metadata-aware completion, safe cache paths, and private application staging.
|
|
62
|
+
There is no process-global live-session registry. A worker and its exact
|
|
63
|
+
provider session belong to one client in one notebook-runtime generation.
|
|
64
|
+
|
|
65
|
+
## Configuration
|
|
66
|
+
|
|
67
|
+
The canonical 1.0 shape is:
|
|
68
|
+
|
|
69
|
+
```toml
|
|
70
|
+
[sql.targets.warehouse]
|
|
71
|
+
provider = "clickhouse"
|
|
72
|
+
host = "db.internal"
|
|
73
|
+
database = "analytics"
|
|
74
|
+
|
|
75
|
+
[sql.targets.reporting]
|
|
76
|
+
provider = "postgres"
|
|
77
|
+
host = "pg.internal"
|
|
78
|
+
dbname = "reports"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Then a cell starts with `%%sql warehouse`. The provider is resolved only inside
|
|
82
|
+
the target kernel against adapters installed in that runtime. Missing, unknown,
|
|
83
|
+
unavailable, and ambiguous providers fail without printing target options. The
|
|
84
|
+
historical `[sql.warehouse]` shape is accepted during migration, but it cannot
|
|
85
|
+
be mixed with `[sql.targets.*]`.
|
|
86
|
+
|
|
87
|
+
Secrets may be provider options because the target worker needs them. They are
|
|
88
|
+
never placed in catalog metadata or error messages. Prefer provider-owned
|
|
89
|
+
environment or secret resolution where possible.
|
|
90
|
+
|
|
91
|
+
## Exact-provider integration
|
|
92
|
+
|
|
93
|
+
Catalog code stays lightweight:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from jusi_sql import sql_catalog_entry
|
|
97
|
+
|
|
98
|
+
def catalog_entry():
|
|
99
|
+
return sql_catalog_entry(
|
|
100
|
+
plugin_id="postgres",
|
|
101
|
+
plugin_version="1.0.0",
|
|
102
|
+
distribution="jusi-postgres",
|
|
103
|
+
kernel_extension="jusi_postgres.kernel",
|
|
104
|
+
worker_entry_point="jusi_postgres.worker:create_worker",
|
|
105
|
+
provider_presentation={"syntax": "pgsql", "indent": "sql"},
|
|
106
|
+
)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The exact kernel module retains its own attested identity while sharing the
|
|
110
|
+
dispatcher:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from jusi_sql.kernel import SqlKernelAdapter
|
|
114
|
+
|
|
115
|
+
_adapter = SqlKernelAdapter(
|
|
116
|
+
plugin_id="postgres",
|
|
117
|
+
plugin_version="1.0.0",
|
|
118
|
+
selectors=("postgres", "postgresql"),
|
|
119
|
+
empty_sql="SELECT 1 WHERE false",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
jusi_kernel_adapter_v1 = _adapter.manifest
|
|
123
|
+
configure_jusi_runtime_v1 = _adapter.configure
|
|
124
|
+
load_ipython_extension = _adapter.load
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Each installed adapter registers its identity in the shared dispatcher. After
|
|
128
|
+
all catalog modules attest, `%%sql` resolves the alias and emits one exact 1.0
|
|
129
|
+
handoff. Registration rejects selector collisions and an unrelated extension
|
|
130
|
+
already owning `%%sql`; it never relies on import order.
|
|
131
|
+
|
|
132
|
+
Worker code uses composition rather than the retired handler hierarchy:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from jusi_sql.worker import SqlWorker
|
|
136
|
+
|
|
137
|
+
def create_worker(context):
|
|
138
|
+
return SqlWorker(context, PostgresSession)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`PostgresSession` implements `execute`, `followup`, `complete`, `interrupt`,
|
|
142
|
+
`editor_action`, and `close`. `interrupt` is called concurrently and must be
|
|
143
|
+
prompt and thread-safe. Recoverable database errors should raise
|
|
144
|
+
`jusi.plugin_api.OperationRejected`; broken sessions should fail normally so
|
|
145
|
+
Jusi fences the worker.
|
|
146
|
+
|
|
147
|
+
## Completion and metadata
|
|
148
|
+
|
|
149
|
+
`complete_sql` consumes a `MetadataSnapshot` and Jusi's full completion payload.
|
|
150
|
+
It returns absolute Unicode code-point ranges, preserves suffix text, handles
|
|
151
|
+
empty prefixes, and understands schema, table, alias, and column qualification.
|
|
152
|
+
Exact providers only collect dialect metadata and supply keyword lists.
|
|
153
|
+
|
|
154
|
+
`MetadataCache` provides stale-while-refresh snapshots.
|
|
155
|
+
`sql_cache_directory` creates stable provider-scoped paths while recursively
|
|
156
|
+
redacting secret values from the fingerprint.
|
|
157
|
+
|
|
158
|
+
Providers using VisiData may install the optional `visidata` extra and use
|
|
159
|
+
`SqlSheetActions`, `bind_sql_actions`, and `install_visidata_commands`. This
|
|
160
|
+
supplies the common numeric/`gf` fetch and `gc`/`gr` transaction commands on
|
|
161
|
+
result sheets and all derived sheets. Live callbacks remain attached to their
|
|
162
|
+
own provider sheet; the family does not keep a global current session.
|
|
163
|
+
|
|
164
|
+
## Migration from 0.x providers
|
|
165
|
+
|
|
166
|
+
Remove `DisplayHandlerSpec`, `BaseSqlHandler`, `SqlSheetRuntime`, environment
|
|
167
|
+
payloads, and the `jusi plugin-runtime` bootstrap. Split each provider into
|
|
168
|
+
catalog, kernel adapter, worker, and terminal-application import boundaries.
|
|
169
|
+
Keep VisiData and driver imports out of catalog and worker startup.
|
|
170
|
+
|
|
171
|
+
PostgreSQL- and ClickHouse-specific connection, streaming, binary-value,
|
|
172
|
+
Kerberos, transaction, and cancellation code remains in those packages. Their
|
|
173
|
+
duplicated target parsing, magic registration, completion models, relation
|
|
174
|
+
parsing, metadata cache, safe cache path, and operation dispatch should be
|
|
175
|
+
deleted in favor of this family package during their 1.0 migrations.
|
jusi_sql-0.2.0/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# jusi-sql
|
|
2
|
+
|
|
3
|
+
`jusi-sql` is the independently installable SQL plugin family for Jusi 1.0.
|
|
4
|
+
It owns the user-facing `%%sql` contract and the provider-neutral code that
|
|
5
|
+
SQLite, PostgreSQL, ClickHouse, and future database plugins should share. It is
|
|
6
|
+
not an exact provider and therefore publishes no `jusi.plugins.v1` entry point.
|
|
7
|
+
|
|
8
|
+
## Family contract
|
|
9
|
+
|
|
10
|
+
Every exact SQL provider advertises the same catalog claim:
|
|
11
|
+
|
|
12
|
+
- family `sql`, magic `sql`
|
|
13
|
+
- capabilities `execute`, `followup`, `complete`, `interrupt`, and
|
|
14
|
+
`editor_actions`
|
|
15
|
+
- shared `sql` syntax and indentation profiles
|
|
16
|
+
- terminal-interactive presentation
|
|
17
|
+
|
|
18
|
+
An exact provider may refine syntax after handoff (for example `pgsql` or
|
|
19
|
+
`clickhouse`), but may not change the shared capabilities or presentation.
|
|
20
|
+
Providers own connections, transactions, dialect metadata queries,
|
|
21
|
+
cancellation, result rendering, selection meaning, and application IPC.
|
|
22
|
+
|
|
23
|
+
The family owns target configuration and selection, deterministic ownership of
|
|
24
|
+
one `%%sql` magic, the initial handoff payload, continuing-operation parsing,
|
|
25
|
+
metadata-aware completion, safe cache paths, and private application staging.
|
|
26
|
+
There is no process-global live-session registry. A worker and its exact
|
|
27
|
+
provider session belong to one client in one notebook-runtime generation.
|
|
28
|
+
|
|
29
|
+
## Configuration
|
|
30
|
+
|
|
31
|
+
The canonical 1.0 shape is:
|
|
32
|
+
|
|
33
|
+
```toml
|
|
34
|
+
[sql.targets.warehouse]
|
|
35
|
+
provider = "clickhouse"
|
|
36
|
+
host = "db.internal"
|
|
37
|
+
database = "analytics"
|
|
38
|
+
|
|
39
|
+
[sql.targets.reporting]
|
|
40
|
+
provider = "postgres"
|
|
41
|
+
host = "pg.internal"
|
|
42
|
+
dbname = "reports"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then a cell starts with `%%sql warehouse`. The provider is resolved only inside
|
|
46
|
+
the target kernel against adapters installed in that runtime. Missing, unknown,
|
|
47
|
+
unavailable, and ambiguous providers fail without printing target options. The
|
|
48
|
+
historical `[sql.warehouse]` shape is accepted during migration, but it cannot
|
|
49
|
+
be mixed with `[sql.targets.*]`.
|
|
50
|
+
|
|
51
|
+
Secrets may be provider options because the target worker needs them. They are
|
|
52
|
+
never placed in catalog metadata or error messages. Prefer provider-owned
|
|
53
|
+
environment or secret resolution where possible.
|
|
54
|
+
|
|
55
|
+
## Exact-provider integration
|
|
56
|
+
|
|
57
|
+
Catalog code stays lightweight:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from jusi_sql import sql_catalog_entry
|
|
61
|
+
|
|
62
|
+
def catalog_entry():
|
|
63
|
+
return sql_catalog_entry(
|
|
64
|
+
plugin_id="postgres",
|
|
65
|
+
plugin_version="1.0.0",
|
|
66
|
+
distribution="jusi-postgres",
|
|
67
|
+
kernel_extension="jusi_postgres.kernel",
|
|
68
|
+
worker_entry_point="jusi_postgres.worker:create_worker",
|
|
69
|
+
provider_presentation={"syntax": "pgsql", "indent": "sql"},
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The exact kernel module retains its own attested identity while sharing the
|
|
74
|
+
dispatcher:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from jusi_sql.kernel import SqlKernelAdapter
|
|
78
|
+
|
|
79
|
+
_adapter = SqlKernelAdapter(
|
|
80
|
+
plugin_id="postgres",
|
|
81
|
+
plugin_version="1.0.0",
|
|
82
|
+
selectors=("postgres", "postgresql"),
|
|
83
|
+
empty_sql="SELECT 1 WHERE false",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
jusi_kernel_adapter_v1 = _adapter.manifest
|
|
87
|
+
configure_jusi_runtime_v1 = _adapter.configure
|
|
88
|
+
load_ipython_extension = _adapter.load
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Each installed adapter registers its identity in the shared dispatcher. After
|
|
92
|
+
all catalog modules attest, `%%sql` resolves the alias and emits one exact 1.0
|
|
93
|
+
handoff. Registration rejects selector collisions and an unrelated extension
|
|
94
|
+
already owning `%%sql`; it never relies on import order.
|
|
95
|
+
|
|
96
|
+
Worker code uses composition rather than the retired handler hierarchy:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from jusi_sql.worker import SqlWorker
|
|
100
|
+
|
|
101
|
+
def create_worker(context):
|
|
102
|
+
return SqlWorker(context, PostgresSession)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`PostgresSession` implements `execute`, `followup`, `complete`, `interrupt`,
|
|
106
|
+
`editor_action`, and `close`. `interrupt` is called concurrently and must be
|
|
107
|
+
prompt and thread-safe. Recoverable database errors should raise
|
|
108
|
+
`jusi.plugin_api.OperationRejected`; broken sessions should fail normally so
|
|
109
|
+
Jusi fences the worker.
|
|
110
|
+
|
|
111
|
+
## Completion and metadata
|
|
112
|
+
|
|
113
|
+
`complete_sql` consumes a `MetadataSnapshot` and Jusi's full completion payload.
|
|
114
|
+
It returns absolute Unicode code-point ranges, preserves suffix text, handles
|
|
115
|
+
empty prefixes, and understands schema, table, alias, and column qualification.
|
|
116
|
+
Exact providers only collect dialect metadata and supply keyword lists.
|
|
117
|
+
|
|
118
|
+
`MetadataCache` provides stale-while-refresh snapshots.
|
|
119
|
+
`sql_cache_directory` creates stable provider-scoped paths while recursively
|
|
120
|
+
redacting secret values from the fingerprint.
|
|
121
|
+
|
|
122
|
+
Providers using VisiData may install the optional `visidata` extra and use
|
|
123
|
+
`SqlSheetActions`, `bind_sql_actions`, and `install_visidata_commands`. This
|
|
124
|
+
supplies the common numeric/`gf` fetch and `gc`/`gr` transaction commands on
|
|
125
|
+
result sheets and all derived sheets. Live callbacks remain attached to their
|
|
126
|
+
own provider sheet; the family does not keep a global current session.
|
|
127
|
+
|
|
128
|
+
## Migration from 0.x providers
|
|
129
|
+
|
|
130
|
+
Remove `DisplayHandlerSpec`, `BaseSqlHandler`, `SqlSheetRuntime`, environment
|
|
131
|
+
payloads, and the `jusi plugin-runtime` bootstrap. Split each provider into
|
|
132
|
+
catalog, kernel adapter, worker, and terminal-application import boundaries.
|
|
133
|
+
Keep VisiData and driver imports out of catalog and worker startup.
|
|
134
|
+
|
|
135
|
+
PostgreSQL- and ClickHouse-specific connection, streaming, binary-value,
|
|
136
|
+
Kerberos, transaction, and cancellation code remains in those packages. Their
|
|
137
|
+
duplicated target parsing, magic registration, completion models, relation
|
|
138
|
+
parsing, metadata cache, safe cache path, and operation dispatch should be
|
|
139
|
+
deleted in favor of this family package during their 1.0 migrations.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "jusi-sql"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "The SQL plugin-family contract and reusable provider toolkit for Jusi 1.0"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { file = "LICENSE" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Jusi contributors" }
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"jusi>=1.0,<2",
|
|
17
|
+
"sqlparse>=0.5,<0.6",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.optional-dependencies]
|
|
21
|
+
visidata = [
|
|
22
|
+
"visidata>=3,<4",
|
|
23
|
+
]
|
|
24
|
+
test = [
|
|
25
|
+
"pytest>=8,<9",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[tool.hatch.build.targets.wheel]
|
|
29
|
+
packages = ["src/jusi_sql"]
|
|
30
|
+
|
|
31
|
+
[tool.pytest.ini_options]
|
|
32
|
+
addopts = "-ra"
|
|
33
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Provider-neutral SQL family primitives for Jusi 1.0.
|
|
2
|
+
|
|
3
|
+
This module intentionally imports neither IPython nor a terminal application.
|
|
4
|
+
Catalog discovery can therefore import it without crossing runtime boundaries.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .catalog import (
|
|
8
|
+
FAMILY_ID,
|
|
9
|
+
MAGIC_NAME,
|
|
10
|
+
SQL_CAPABILITIES,
|
|
11
|
+
SQL_PRESENTATION,
|
|
12
|
+
sql_catalog_entry,
|
|
13
|
+
sql_family_claim,
|
|
14
|
+
)
|
|
15
|
+
from .completion import (
|
|
16
|
+
CompletionColumn,
|
|
17
|
+
CompletionItem,
|
|
18
|
+
CompletionObject,
|
|
19
|
+
MetadataSnapshot,
|
|
20
|
+
SqlCompletionRequest,
|
|
21
|
+
complete_sql,
|
|
22
|
+
parse_query_relations,
|
|
23
|
+
)
|
|
24
|
+
from .config import (
|
|
25
|
+
ResolvedSqlTarget,
|
|
26
|
+
SqlConfigError,
|
|
27
|
+
SqlFamilyConfig,
|
|
28
|
+
SqlProviderIdentity,
|
|
29
|
+
SqlTarget,
|
|
30
|
+
resolve_sql_target,
|
|
31
|
+
)
|
|
32
|
+
from .metadata import MetadataCache, sql_cache_directory
|
|
33
|
+
from .visidata import SqlSheetActions, bind_sql_actions, find_sql_actions, install_visidata_commands
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
"FAMILY_ID",
|
|
37
|
+
"MAGIC_NAME",
|
|
38
|
+
"SQL_CAPABILITIES",
|
|
39
|
+
"SQL_PRESENTATION",
|
|
40
|
+
"CompletionColumn",
|
|
41
|
+
"CompletionItem",
|
|
42
|
+
"CompletionObject",
|
|
43
|
+
"MetadataSnapshot",
|
|
44
|
+
"MetadataCache",
|
|
45
|
+
"ResolvedSqlTarget",
|
|
46
|
+
"SqlCompletionRequest",
|
|
47
|
+
"SqlConfigError",
|
|
48
|
+
"SqlFamilyConfig",
|
|
49
|
+
"SqlProviderIdentity",
|
|
50
|
+
"SqlSheetActions",
|
|
51
|
+
"SqlTarget",
|
|
52
|
+
"complete_sql",
|
|
53
|
+
"bind_sql_actions",
|
|
54
|
+
"find_sql_actions",
|
|
55
|
+
"install_visidata_commands",
|
|
56
|
+
"parse_query_relations",
|
|
57
|
+
"resolve_sql_target",
|
|
58
|
+
"sql_catalog_entry",
|
|
59
|
+
"sql_cache_directory",
|
|
60
|
+
"sql_family_claim",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
__version__ = "0.2.0"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Iterable, Mapping
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
FAMILY_ID = "sql"
|
|
7
|
+
MAGIC_NAME = "sql"
|
|
8
|
+
SQL_CAPABILITIES = ("execute", "followup", "complete", "interrupt", "editor_actions")
|
|
9
|
+
SQL_PRESENTATION = {"syntax": "sql", "indent": "sql"}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def sql_family_claim(
|
|
13
|
+
*,
|
|
14
|
+
provider_presentation: Mapping[str, str] | None = None,
|
|
15
|
+
) -> dict[str, Any]:
|
|
16
|
+
"""Return the one canonical catalog claim shared by every SQL provider."""
|
|
17
|
+
claim: dict[str, Any] = {
|
|
18
|
+
"family_id": FAMILY_ID,
|
|
19
|
+
"magic_name": MAGIC_NAME,
|
|
20
|
+
"capabilities": list(SQL_CAPABILITIES),
|
|
21
|
+
"presentation": dict(SQL_PRESENTATION),
|
|
22
|
+
}
|
|
23
|
+
if provider_presentation:
|
|
24
|
+
claim["provider_presentation"] = dict(provider_presentation)
|
|
25
|
+
return claim
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def sql_catalog_entry(
|
|
29
|
+
*,
|
|
30
|
+
plugin_id: str,
|
|
31
|
+
plugin_version: str,
|
|
32
|
+
distribution: str,
|
|
33
|
+
kernel_extension: str,
|
|
34
|
+
worker_entry_point: str,
|
|
35
|
+
provider_presentation: Mapping[str, str] | None = None,
|
|
36
|
+
media_types: Iterable[str] = ("text/x-ansi",),
|
|
37
|
+
) -> dict[str, Any]:
|
|
38
|
+
"""Build an exact-provider catalog entry without importing runtime code."""
|
|
39
|
+
return {
|
|
40
|
+
"plugin_id": _required(plugin_id, "plugin_id"),
|
|
41
|
+
"plugin_version": _required(plugin_version, "plugin_version"),
|
|
42
|
+
"distribution": _required(distribution, "distribution"),
|
|
43
|
+
"families": [sql_family_claim(provider_presentation=provider_presentation)],
|
|
44
|
+
"kernel_extensions": [_required(kernel_extension, "kernel_extension")],
|
|
45
|
+
"worker_entry_point": _required(worker_entry_point, "worker_entry_point"),
|
|
46
|
+
"media_types": list(dict.fromkeys(media_types)),
|
|
47
|
+
"interaction": "terminal_interactive",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _required(value: str, name: str) -> str:
|
|
52
|
+
normalized = str(value).strip()
|
|
53
|
+
if not normalized:
|
|
54
|
+
raise ValueError(f"{name} must be a non-empty string")
|
|
55
|
+
return normalized
|