execsql2 2.22.3__py3-none-any.whl → 2.22.4__py3-none-any.whl
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.
- execsql/gui/base.py +56 -1
- execsql/gui/console.py +10 -33
- execsql/gui/tui.py +45 -15
- execsql/metacommands/control.py +26 -0
- {execsql2-2.22.3.dist-info → execsql2-2.22.4.dist-info}/METADATA +3 -3
- {execsql2-2.22.3.dist-info → execsql2-2.22.4.dist-info}/RECORD +24 -24
- {execsql2-2.22.3.dist-info → execsql2-2.22.4.dist-info}/WHEEL +1 -1
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/README.md +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/config_settings.sqlite +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/make_config_db.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/md_compare.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/md_glossary.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/md_upsert.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/pg_compare.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/pg_glossary.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/pg_upsert.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/script_template.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/ss_compare.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/ss_glossary.sql +0 -0
- {execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/ss_upsert.sql +0 -0
- {execsql2-2.22.3.dist-info → execsql2-2.22.4.dist-info}/entry_points.txt +0 -0
- {execsql2-2.22.3.dist-info → execsql2-2.22.4.dist-info}/licenses/LICENSE.txt +0 -0
- {execsql2-2.22.3.dist-info → execsql2-2.22.4.dist-info}/licenses/NOTICE +0 -0
execsql/gui/base.py
CHANGED
|
@@ -9,11 +9,66 @@ from typing import TYPE_CHECKING, Any
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
pass
|
|
11
11
|
|
|
12
|
-
__all__ = ["DiffResult", "GuiBackend", "compare_stats", "compute_row_diffs"]
|
|
12
|
+
__all__ = ["DiffResult", "GuiBackend", "compare_stats", "compute_row_diffs", "format_table", "row_count_text"]
|
|
13
13
|
|
|
14
14
|
DIFF_MARKER = "● "
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Plain-text table rendering (shared by the console backend and by
|
|
19
|
+
# non-interactive metacommand fallbacks such as HALT ... DISPLAY)
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def row_count_text(n: int) -> str:
|
|
24
|
+
"""Return a human-readable row count string, e.g. ``'3 rows'`` or ``'1 row'``."""
|
|
25
|
+
return f"{n:,} row{'s' if n != 1 else ''}"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def format_table(
|
|
29
|
+
headers: list,
|
|
30
|
+
rows: list,
|
|
31
|
+
row_states: list[str] | None = None,
|
|
32
|
+
changed_cols: list[set[str]] | None = None,
|
|
33
|
+
) -> str:
|
|
34
|
+
"""Render *headers* and *rows* as a plain-text table.
|
|
35
|
+
|
|
36
|
+
Columns are left-aligned and padded to the widest value. When *row_states*
|
|
37
|
+
and *changed_cols* are provided, cells that differ in ``"changed"`` rows are
|
|
38
|
+
prefixed with the diff marker (``"● "``) and the marker width is included in
|
|
39
|
+
the column sizing.
|
|
40
|
+
|
|
41
|
+
Returns an empty string when *headers* is empty. The result has no trailing
|
|
42
|
+
newline.
|
|
43
|
+
"""
|
|
44
|
+
if not headers:
|
|
45
|
+
return ""
|
|
46
|
+
headers_str = [str(h) for h in headers]
|
|
47
|
+
|
|
48
|
+
# Pre-compute display values so column widths account for markers.
|
|
49
|
+
display_rows: list[list[str]] = []
|
|
50
|
+
for ridx, row in enumerate(rows):
|
|
51
|
+
cells: list[str] = []
|
|
52
|
+
state = row_states[ridx] if row_states and ridx < len(row_states) else ""
|
|
53
|
+
diff_set = changed_cols[ridx] if changed_cols and ridx < len(changed_cols) else set()
|
|
54
|
+
for ci, cell in enumerate(row):
|
|
55
|
+
val = str(cell) if cell is not None else ""
|
|
56
|
+
if state == "changed" and ci < len(headers_str) and headers_str[ci] in diff_set:
|
|
57
|
+
val = f"{DIFF_MARKER}{val}"
|
|
58
|
+
cells.append(val)
|
|
59
|
+
display_rows.append(cells)
|
|
60
|
+
|
|
61
|
+
col_widths = [len(h) for h in headers_str]
|
|
62
|
+
for cells in display_rows:
|
|
63
|
+
for i, cell in enumerate(cells):
|
|
64
|
+
col_widths[i] = max(col_widths[i], len(cell))
|
|
65
|
+
fmt = " " + " ".join(f"{{:<{w}}}" for w in col_widths)
|
|
66
|
+
sep = " " + " ".join("-" * w for w in col_widths)
|
|
67
|
+
lines = [fmt.format(*headers_str), sep]
|
|
68
|
+
lines.extend(fmt.format(*cells) for cells in display_rows)
|
|
69
|
+
return "\n".join(lines)
|
|
70
|
+
|
|
71
|
+
|
|
17
72
|
# ---------------------------------------------------------------------------
|
|
18
73
|
# Value comparison helpers
|
|
19
74
|
# ---------------------------------------------------------------------------
|
execsql/gui/console.py
CHANGED
|
@@ -11,7 +11,13 @@ import sys
|
|
|
11
11
|
import time
|
|
12
12
|
from typing import Any, cast
|
|
13
13
|
|
|
14
|
-
from execsql.gui.base import
|
|
14
|
+
from execsql.gui.base import (
|
|
15
|
+
GuiBackend,
|
|
16
|
+
compare_stats as _compare_stats,
|
|
17
|
+
compute_row_diffs,
|
|
18
|
+
format_table,
|
|
19
|
+
row_count_text as _row_count_text,
|
|
20
|
+
)
|
|
15
21
|
|
|
16
22
|
__all__ = ["ConsoleBackend"]
|
|
17
23
|
|
|
@@ -23,11 +29,6 @@ def _print_help_url(args: dict) -> None:
|
|
|
23
29
|
print(f" Help: {url}", file=sys.stderr)
|
|
24
30
|
|
|
25
31
|
|
|
26
|
-
def _row_count_text(n: int) -> str:
|
|
27
|
-
"""Return a human-readable row count string, e.g. '3 rows' or '1 row'."""
|
|
28
|
-
return f"{n:,} row{'s' if n != 1 else ''}"
|
|
29
|
-
|
|
30
|
-
|
|
31
32
|
def _print_table(
|
|
32
33
|
headers: list,
|
|
33
34
|
rows: list,
|
|
@@ -42,33 +43,9 @@ def _print_table(
|
|
|
42
43
|
"""
|
|
43
44
|
if file is None:
|
|
44
45
|
file = sys.stderr
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
# Pre-compute display values so column widths account for markers.
|
|
50
|
-
display_rows: list[list[str]] = []
|
|
51
|
-
for ridx, row in enumerate(rows):
|
|
52
|
-
cells: list[str] = []
|
|
53
|
-
state = row_states[ridx] if row_states and ridx < len(row_states) else ""
|
|
54
|
-
diff_set = changed_cols[ridx] if changed_cols and ridx < len(changed_cols) else set()
|
|
55
|
-
for ci, cell in enumerate(row):
|
|
56
|
-
val = str(cell) if cell is not None else ""
|
|
57
|
-
if state == "changed" and ci < len(headers_str) and headers_str[ci] in diff_set:
|
|
58
|
-
val = f"{DIFF_MARKER}{val}"
|
|
59
|
-
cells.append(val)
|
|
60
|
-
display_rows.append(cells)
|
|
61
|
-
|
|
62
|
-
col_widths = [len(h) for h in headers_str]
|
|
63
|
-
for cells in display_rows:
|
|
64
|
-
for i, cell in enumerate(cells):
|
|
65
|
-
col_widths[i] = max(col_widths[i], len(cell))
|
|
66
|
-
fmt = " " + " ".join(f"{{:<{w}}}" for w in col_widths)
|
|
67
|
-
sep = " " + " ".join("-" * w for w in col_widths)
|
|
68
|
-
print(fmt.format(*headers_str), file=file)
|
|
69
|
-
print(sep, file=file)
|
|
70
|
-
for cells in display_rows:
|
|
71
|
-
print(fmt.format(*cells), file=file)
|
|
46
|
+
rendered = format_table(headers, rows, row_states=row_states, changed_cols=changed_cols)
|
|
47
|
+
if rendered:
|
|
48
|
+
print(rendered, file=file)
|
|
72
49
|
|
|
73
50
|
|
|
74
51
|
def _prompt_buttons(button_list: list) -> int | None:
|
execsql/gui/tui.py
CHANGED
|
@@ -89,14 +89,18 @@ def _help_button(url: str | None) -> Button | None:
|
|
|
89
89
|
return None
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
def _button_row(button_list: list) -> list[Button]:
|
|
92
|
+
def _button_row(button_list: list, no_cancel: bool = False) -> list[Button]:
|
|
93
93
|
"""Create Button widgets from a button_list of (label, value, key?) tuples.
|
|
94
94
|
|
|
95
|
-
A Cancel button (id ``btn_cancel_exit``) is
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
A Cancel button (id ``btn_cancel_exit``) is prepended so it appears on the
|
|
96
|
+
left while the primary action button sits on the far right. Entries in
|
|
97
|
+
*button_list* with a falsy value (0 or None) are treated as the cancel
|
|
98
|
+
label source and are otherwise excluded from the numbered buttons so that
|
|
99
|
+
``btn_N`` indices stay aligned with ``button_list`` positions.
|
|
100
|
+
|
|
101
|
+
When *no_cancel* is set, the Cancel button is omitted — dialogs such as
|
|
102
|
+
HALT have no meaningful cancel action, and cancelling one would exit with
|
|
103
|
+
the generic status 2 rather than the status the caller asked for.
|
|
100
104
|
"""
|
|
101
105
|
cancel_label = "Cancel"
|
|
102
106
|
primary_buttons = []
|
|
@@ -107,6 +111,8 @@ def _button_row(button_list: list) -> list[Button]:
|
|
|
107
111
|
else:
|
|
108
112
|
variant: Literal["primary", "default"] = "primary" if i == 0 else "default"
|
|
109
113
|
primary_buttons.append(Button(label, id=f"btn_{i}", variant=variant))
|
|
114
|
+
if no_cancel:
|
|
115
|
+
return primary_buttons
|
|
110
116
|
return [Button(cancel_label, id="btn_cancel_exit", variant="warning")] + primary_buttons
|
|
111
117
|
|
|
112
118
|
|
|
@@ -182,7 +188,14 @@ class _BaseDialog(ModalScreen):
|
|
|
182
188
|
return self._result
|
|
183
189
|
|
|
184
190
|
def action_cancel(self) -> None:
|
|
185
|
-
"""Dismiss the dialog as cancelled (triggered by Escape key).
|
|
191
|
+
"""Dismiss the dialog as cancelled (triggered by Escape key).
|
|
192
|
+
|
|
193
|
+
Ignored for dialogs that pass ``no_cancel`` (e.g. HALT), which have no
|
|
194
|
+
meaningful cancel action. This matches the Tkinter backend, which does
|
|
195
|
+
not bind ``<Escape>`` to cancellation in that case.
|
|
196
|
+
"""
|
|
197
|
+
if self.args.get("no_cancel", False):
|
|
198
|
+
return
|
|
186
199
|
self._result = {"button": None, "cancelled": True}
|
|
187
200
|
self.dismiss(self._result)
|
|
188
201
|
|
|
@@ -210,31 +223,48 @@ class _BaseDialog(ModalScreen):
|
|
|
210
223
|
|
|
211
224
|
|
|
212
225
|
class MsgScreen(_BaseDialog):
|
|
213
|
-
"""
|
|
226
|
+
"""Message dialog with an optional data table.
|
|
227
|
+
|
|
228
|
+
Honours the caller's ``button_list`` and ``no_cancel`` arguments, and
|
|
229
|
+
renders ``column_headers``/``rowset`` when supplied (as the HALT
|
|
230
|
+
metacommand's DISPLAY clause does), matching the Tkinter MsgDialog.
|
|
231
|
+
"""
|
|
214
232
|
|
|
215
233
|
BINDINGS = [
|
|
216
234
|
*_BaseDialog.BINDINGS,
|
|
217
235
|
Binding("enter", "submit", "Continue", show=True),
|
|
218
236
|
]
|
|
219
237
|
|
|
238
|
+
def _button_list(self) -> list:
|
|
239
|
+
return cast(list, self.args.get("button_list") or [("Continue", 1, "<Return>")])
|
|
240
|
+
|
|
220
241
|
def compose(self) -> ComposeResult:
|
|
221
242
|
title = self.args.get("title", "Message")
|
|
222
243
|
message = self.args.get("message", "")
|
|
244
|
+
headers = self.args.get("column_headers")
|
|
245
|
+
rows = self.args.get("rowset")
|
|
223
246
|
with Container(id="dialog"):
|
|
224
247
|
yield Label(title, id="title")
|
|
225
248
|
yield Static(message, id="message")
|
|
249
|
+
if headers and rows:
|
|
250
|
+
with ScrollableContainer(id="table_container"):
|
|
251
|
+
yield _make_table_widget("msg_table", headers, rows)
|
|
252
|
+
yield Static(_row_count_text(len(rows)), classes="row-count")
|
|
226
253
|
with Horizontal(id="buttons"):
|
|
227
|
-
yield
|
|
228
|
-
yield Button("Continue", id="btn_close", variant="primary")
|
|
254
|
+
yield from _button_row(self._button_list(), no_cancel=self.args.get("no_cancel", False))
|
|
229
255
|
|
|
230
256
|
def action_submit(self) -> None:
|
|
231
|
-
"""
|
|
232
|
-
self.
|
|
233
|
-
|
|
257
|
+
"""Dismiss with the first non-cancel button value (triggered by Enter)."""
|
|
258
|
+
for btn in self._button_list():
|
|
259
|
+
if btn[1]:
|
|
260
|
+
self._result = {"button": btn[1]}
|
|
261
|
+
self.dismiss(self._result)
|
|
262
|
+
return
|
|
234
263
|
|
|
235
264
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
236
|
-
|
|
237
|
-
|
|
265
|
+
btn_id = event.button.id
|
|
266
|
+
if btn_id and btn_id.startswith("btn_") and btn_id[4:].isdigit():
|
|
267
|
+
self._result = {"button": self._button_list()[int(btn_id[4:])][1]}
|
|
238
268
|
self.dismiss(self._result)
|
|
239
269
|
|
|
240
270
|
|
execsql/metacommands/control.py
CHANGED
|
@@ -33,6 +33,7 @@ from execsql.exceptions import ErrInfo
|
|
|
33
33
|
from typing import Any
|
|
34
34
|
|
|
35
35
|
import execsql.state as _state
|
|
36
|
+
from execsql.gui.base import format_table, row_count_text
|
|
36
37
|
from execsql.script import current_script_line
|
|
37
38
|
from execsql.utils.errors import exit_now
|
|
38
39
|
from execsql.utils.fileio import EncodedFile, check_dir
|
|
@@ -214,6 +215,14 @@ def x_wait_until(**kwargs: Any) -> None:
|
|
|
214
215
|
|
|
215
216
|
# x_halt_msg is also needed by x_halt - define it here
|
|
216
217
|
def x_halt_msg(**kwargs: Any) -> None:
|
|
218
|
+
"""Halt the script, reporting *errmsg* in a dialog or on the console.
|
|
219
|
+
|
|
220
|
+
The dialog is used only when the run is interactive — either a GUI console
|
|
221
|
+
is already running, or ``gui_level`` is greater than 1. Otherwise the
|
|
222
|
+
message (and any ``DISPLAY`` rowset) is written to the error output and the
|
|
223
|
+
script exits, so that unattended runs fail instead of blocking forever on a
|
|
224
|
+
modal nobody can dismiss.
|
|
225
|
+
"""
|
|
217
226
|
import queue as _queue
|
|
218
227
|
|
|
219
228
|
errmsg = kwargs["errmsg"]
|
|
@@ -242,6 +251,23 @@ def x_halt_msg(**kwargs: Any) -> None:
|
|
|
242
251
|
headers, rows = db.select_data(sql)
|
|
243
252
|
else:
|
|
244
253
|
headers, rows = None, None
|
|
254
|
+
|
|
255
|
+
# Non-interactive runs (no GUI console, gui_level 0 or 1) must not block on
|
|
256
|
+
# a modal dialog: report on the console and exit instead. This mirrors the
|
|
257
|
+
# guard in x_halt, which the message-bearing HALT forms never reach because
|
|
258
|
+
# their metacommand patterns are registered later and so take priority.
|
|
259
|
+
if not (gui_console_isrunning() or conf.gui_level > 1):
|
|
260
|
+
if errmsg:
|
|
261
|
+
_state.output.write_err(errmsg)
|
|
262
|
+
if headers:
|
|
263
|
+
# Unlike the dialog, render an empty rowset too — a HALT diagnostic
|
|
264
|
+
# showing zero rows is more useful than showing nothing at all.
|
|
265
|
+
_state.output.write_err(format_table(headers, rows or []))
|
|
266
|
+
_state.output.write_err(row_count_text(len(rows or [])))
|
|
267
|
+
_state.exec_log.log_exit_halt(*current_script_line(), msg=errmsg)
|
|
268
|
+
exit_now(errlevel, None)
|
|
269
|
+
return
|
|
270
|
+
|
|
245
271
|
enable_gui()
|
|
246
272
|
return_queue: _queue.Queue[Any] = _queue.Queue()
|
|
247
273
|
gui_args = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.22.
|
|
3
|
+
Version: 2.22.4
|
|
4
4
|
Summary: Runs a SQL script against a PostgreSQL, SQLite, MariaDB/MySQL, DuckDB, Firebird, MS-Access, MS-SQL-Server, or Oracle database, or an ODBC DSN. Provides metacommands to import and export data, copy data between databases, conditionally execute SQL and metacommands, and dynamically alter SQL and metacommands with substitution variables.
|
|
5
5
|
Project-URL: Homepage, https://execsql2.readthedocs.io
|
|
6
6
|
Project-URL: Repository, https://github.com/geocoug/execsql
|
|
@@ -384,7 +384,7 @@ execsql-format --no-sql --in-place scripts/
|
|
|
384
384
|
```yaml
|
|
385
385
|
repos:
|
|
386
386
|
- repo: https://github.com/geocoug/execsql
|
|
387
|
-
rev: v2.22.
|
|
387
|
+
rev: v2.22.4
|
|
388
388
|
hooks:
|
|
389
389
|
- id: execsql-format
|
|
390
390
|
```
|
|
@@ -55,10 +55,10 @@ execsql/exporters/xml.py,sha256=t1PSr3i8xvTCWzd9jaxxAy5NcRpl6sqjnZALafKCqpM,2575
|
|
|
55
55
|
execsql/exporters/yaml.py,sha256=R61Rs_0rd5G3bg344L4hC84GM79IfYXaDO2tkF-BluY,3121
|
|
56
56
|
execsql/exporters/zip.py,sha256=341z4Z4MPtEkXJEtfiMSiuJigERh5_f8RDbNMBbt8KM,5078
|
|
57
57
|
execsql/gui/__init__.py,sha256=oCb-cyhLZzVpWJ4WU5HbqEDBrV-lm0ytEwxemrOZyqs,2048
|
|
58
|
-
execsql/gui/base.py,sha256=
|
|
59
|
-
execsql/gui/console.py,sha256=
|
|
58
|
+
execsql/gui/base.py,sha256=DMTqHLlpZlGCsNKyrLlJPbaxvukC0n1YmR4aHEN3jPY,14983
|
|
59
|
+
execsql/gui/console.py,sha256=dzdSl4NJNvRd9VvlwRCXHvfnXjQPimyTx7NcibcUZC8,18305
|
|
60
60
|
execsql/gui/desktop.py,sha256=922OdzjV4OGNDIesOxKOmlsrNp1aJ8St8cVwED0H2sE,59521
|
|
61
|
-
execsql/gui/tui.py,sha256=
|
|
61
|
+
execsql/gui/tui.py,sha256=jlCoP1lsEJgFsFikKVqF4B3s3KyKRs6JbWfwtlFHyDc,66800
|
|
62
62
|
execsql/importers/__init__.py,sha256=zZwdQxMaValCNqUrVdvaA7XPU3J8NmqVJ4uolNWY2iU,299
|
|
63
63
|
execsql/importers/base.py,sha256=3Iq_Sr4cCXKHpjjJYkhZX6uhsIIRAdmvAvTdC4mFlWo,4326
|
|
64
64
|
execsql/importers/csv.py,sha256=Kec1VCycRdfstNoxIXsEsSFqQprZp_edpNiMZm43eTI,4914
|
|
@@ -69,7 +69,7 @@ execsql/importers/xls.py,sha256=D7Ul42gIRYZZC5QxD35ft_wmqQv2f1jNMSbnqlzV0ZA,3851
|
|
|
69
69
|
execsql/metacommands/__init__.py,sha256=H_D1Z5kN6zfYtxatejQhQhQV1tlVZ7rcdFZ_9uhXu2Q,13010
|
|
70
70
|
execsql/metacommands/conditions.py,sha256=2bfdVV_LCl91quG4SRLur9Jk60NsIOStHlBCeJJ-Djc,30068
|
|
71
71
|
execsql/metacommands/connect.py,sha256=SPk4h9yiUgTD3w1gNOT_oYx8VShggsO357by5Hoy6OI,15344
|
|
72
|
-
execsql/metacommands/control.py,sha256=
|
|
72
|
+
execsql/metacommands/control.py,sha256=QT3CJyneANrHxgnbK7vlwmLbckRCbSSwSxy4D3oxN4A,9375
|
|
73
73
|
execsql/metacommands/data.py,sha256=Rp18lHUKSTkwTFRjOQ7bDgZd42LNLVoTS3Zc_bcNEWY,12199
|
|
74
74
|
execsql/metacommands/debug.py,sha256=MeVXAob8ItEg2QzuSUkKDaQCEABnH6u0XcAwJzw36CE,13015
|
|
75
75
|
execsql/metacommands/dispatch.py,sha256=t7x0xWHJA0PeCrYf7jYeSMJgf0yxcZ_xh-_YAtBPHLw,87192
|
|
@@ -101,23 +101,23 @@ execsql/utils/numeric.py,sha256=_7bi5R6pHjMCkOPne_Sh5nUj-B8e9g6WFmjptFHaunA,1573
|
|
|
101
101
|
execsql/utils/regex.py,sha256=B3mSBhRRx_DpUnX_t9IoYd05KvWAebiLMCZqQAmEwcw,3885
|
|
102
102
|
execsql/utils/strings.py,sha256=UQNjpRCEFa1UO6feU-M-9e24wWAvizs_iu_4fFusLxo,8516
|
|
103
103
|
execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
|
|
104
|
-
execsql2-2.22.
|
|
105
|
-
execsql2-2.22.
|
|
106
|
-
execsql2-2.22.
|
|
107
|
-
execsql2-2.22.
|
|
108
|
-
execsql2-2.22.
|
|
109
|
-
execsql2-2.22.
|
|
110
|
-
execsql2-2.22.
|
|
111
|
-
execsql2-2.22.
|
|
112
|
-
execsql2-2.22.
|
|
113
|
-
execsql2-2.22.
|
|
114
|
-
execsql2-2.22.
|
|
115
|
-
execsql2-2.22.
|
|
116
|
-
execsql2-2.22.
|
|
117
|
-
execsql2-2.22.
|
|
118
|
-
execsql2-2.22.
|
|
119
|
-
execsql2-2.22.
|
|
120
|
-
execsql2-2.22.
|
|
121
|
-
execsql2-2.22.
|
|
122
|
-
execsql2-2.22.
|
|
123
|
-
execsql2-2.22.
|
|
104
|
+
execsql2-2.22.4.data/data/execsql2_extras/README.md,sha256=vX4NTL095dUoA_hesyRMGYBorEZ_Y_tJ9qrd-MVV09I,5032
|
|
105
|
+
execsql2-2.22.4.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
|
|
106
|
+
execsql2-2.22.4.data/data/execsql2_extras/example_config_prompt.sql,sha256=2e8KzzVWhho8KxYVHETSVmZdhW7wodioDsqBLSL6m4s,7487
|
|
107
|
+
execsql2-2.22.4.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
|
|
108
|
+
execsql2-2.22.4.data/data/execsql2_extras/md_compare.sql,sha256=qYYVAjSeHZzjszxV3Bv6bg8Ckbq2kMHl87_gh4sywMU,24140
|
|
109
|
+
execsql2-2.22.4.data/data/execsql2_extras/md_glossary.sql,sha256=hkZ2Onn57LAKKsuXxzhR8tPtcWXkmWEQkwPE58-Tm2k,10796
|
|
110
|
+
execsql2-2.22.4.data/data/execsql2_extras/md_upsert.sql,sha256=_CAK4BzEboRXTNy03SJR-oOjcEdSNMuRBPL6noWUptY,112560
|
|
111
|
+
execsql2-2.22.4.data/data/execsql2_extras/pg_compare.sql,sha256=1zJd4hVUKHR0tncc2qTBC9B4qVV4Us2ITkJpsjN3tMw,24352
|
|
112
|
+
execsql2-2.22.4.data/data/execsql2_extras/pg_glossary.sql,sha256=IKuwna-_8b20ljSkXZruuiQigrCpo7ueQdUqd1MXiuI,9908
|
|
113
|
+
execsql2-2.22.4.data/data/execsql2_extras/pg_upsert.sql,sha256=HpPJtTHvpEjQy03j-3iPxDEOHMRkudOg7O4D4YR38UI,108315
|
|
114
|
+
execsql2-2.22.4.data/data/execsql2_extras/script_template.sql,sha256=2J35ddZPguJ-vwTsz83wErv0jiWUyJcdW_JM0mNKDXA,11155
|
|
115
|
+
execsql2-2.22.4.data/data/execsql2_extras/ss_compare.sql,sha256=j1qVNUPXQsEU7-DoVgDJCGcE0EuIl7whLBT3fgeiMAo,24833
|
|
116
|
+
execsql2-2.22.4.data/data/execsql2_extras/ss_glossary.sql,sha256=2gLxv34xzKt0vy7hSzJH7a9JiMC3ETrv9MofxQwAibU,13065
|
|
117
|
+
execsql2-2.22.4.data/data/execsql2_extras/ss_upsert.sql,sha256=G_8rQ0VzuKIZHWs24O_WrfzpC5S27R1JsL-bFBR3SUQ,117730
|
|
118
|
+
execsql2-2.22.4.dist-info/METADATA,sha256=gD2Dm8BheKQrFz6xAs7KyfpqGzs93Rpv7vxWyPWXeQE,20382
|
|
119
|
+
execsql2-2.22.4.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
120
|
+
execsql2-2.22.4.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
|
|
121
|
+
execsql2-2.22.4.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
|
|
122
|
+
execsql2-2.22.4.dist-info/licenses/NOTICE,sha256=McYzgxYav3U1OaVsY4Su1sfBrfmplpRdA9b6-gCDQCg,342
|
|
123
|
+
execsql2-2.22.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{execsql2-2.22.3.data → execsql2-2.22.4.data}/data/execsql2_extras/example_config_prompt.sql
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
|