execsql2 2.0.1__py3-none-any.whl → 2.1.2__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/cli.py +322 -108
- execsql/config.py +134 -114
- execsql/db/access.py +89 -65
- execsql/db/base.py +97 -68
- execsql/db/dsn.py +45 -29
- execsql/db/duckdb.py +4 -5
- execsql/db/factory.py +27 -27
- execsql/db/firebird.py +30 -18
- execsql/db/mysql.py +38 -14
- execsql/db/oracle.py +58 -33
- execsql/db/postgres.py +68 -28
- execsql/db/sqlite.py +36 -27
- execsql/db/sqlserver.py +45 -30
- execsql/exceptions.py +68 -64
- execsql/exporters/__init__.py +1 -1
- execsql/exporters/base.py +42 -17
- execsql/exporters/delimited.py +60 -59
- execsql/exporters/duckdb.py +8 -12
- execsql/exporters/feather.py +32 -24
- execsql/exporters/html.py +33 -30
- execsql/exporters/json.py +18 -17
- execsql/exporters/latex.py +11 -13
- execsql/exporters/ods.py +50 -46
- execsql/exporters/parquet.py +32 -0
- execsql/exporters/pretty.py +16 -15
- execsql/exporters/raw.py +9 -11
- execsql/exporters/sqlite.py +38 -38
- execsql/exporters/templates.py +15 -72
- execsql/exporters/values.py +13 -12
- execsql/exporters/xls.py +26 -26
- execsql/exporters/xml.py +12 -12
- execsql/exporters/zip.py +0 -3
- execsql/gui/__init__.py +2 -2
- execsql/gui/console.py +0 -1
- execsql/gui/desktop.py +6 -7
- execsql/gui/tui.py +8 -14
- execsql/importers/base.py +6 -9
- execsql/importers/csv.py +10 -17
- execsql/importers/feather.py +16 -22
- execsql/importers/ods.py +3 -4
- execsql/importers/xls.py +5 -6
- execsql/metacommands/__init__.py +8 -8
- execsql/metacommands/conditions.py +41 -33
- execsql/metacommands/connect.py +113 -99
- execsql/metacommands/control.py +38 -26
- execsql/metacommands/data.py +35 -33
- execsql/metacommands/debug.py +13 -9
- execsql/metacommands/io.py +288 -229
- execsql/metacommands/prompt.py +179 -157
- execsql/metacommands/script_ext.py +11 -9
- execsql/metacommands/system.py +44 -25
- execsql/models.py +9 -16
- execsql/parser.py +10 -10
- execsql/script.py +183 -157
- execsql/state.py +170 -208
- execsql/types.py +46 -81
- execsql/utils/auth.py +114 -14
- execsql/utils/crypto.py +31 -4
- execsql/utils/datetime.py +7 -7
- execsql/utils/errors.py +34 -29
- execsql/utils/fileio.py +90 -55
- execsql/utils/gui.py +22 -23
- execsql/utils/mail.py +15 -17
- execsql/utils/numeric.py +2 -3
- execsql/utils/regex.py +9 -12
- execsql/utils/strings.py +10 -12
- execsql/utils/timer.py +0 -2
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/execsql.conf +1 -1
- execsql2-2.1.2.dist-info/METADATA +300 -0
- execsql2-2.1.2.dist-info/RECORD +96 -0
- execsql2-2.0.1.dist-info/METADATA +0 -406
- execsql2-2.0.1.dist-info/RECORD +0 -95
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/READ_ME.rst +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/config_settings.sqlite +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/make_config_db.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/md_compare.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/md_glossary.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/md_upsert.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/pg_compare.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/pg_glossary.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/pg_upsert.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/script_template.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/ss_compare.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/ss_glossary.sql +0 -0
- {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/ss_upsert.sql +0 -0
- {execsql2-2.0.1.dist-info → execsql2-2.1.2.dist-info}/WHEEL +0 -0
- {execsql2-2.0.1.dist-info → execsql2-2.1.2.dist-info}/entry_points.txt +0 -0
- {execsql2-2.0.1.dist-info → execsql2-2.1.2.dist-info}/licenses/LICENSE.txt +0 -0
- {execsql2-2.0.1.dist-info → execsql2-2.1.2.dist-info}/licenses/NOTICE +0 -0
execsql/metacommands/prompt.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
from execsql.exceptions import ErrInfo
|
|
2
3
|
|
|
3
4
|
"""
|
|
4
5
|
Interactive user prompt metacommand handlers for execsql.
|
|
@@ -22,9 +23,39 @@ console prompts to the user:
|
|
|
22
23
|
|
|
23
24
|
import os
|
|
24
25
|
import queue as _queue
|
|
26
|
+
from pathlib import Path
|
|
25
27
|
from typing import Any
|
|
26
28
|
|
|
27
29
|
import execsql.state as _state
|
|
30
|
+
from execsql.script import current_script_line
|
|
31
|
+
from execsql.utils.errors import exception_desc, exit_now
|
|
32
|
+
from execsql.utils.fileio import EncodedFile, check_dir
|
|
33
|
+
from execsql.utils.gui import (
|
|
34
|
+
ActionSpec,
|
|
35
|
+
EntrySpec,
|
|
36
|
+
GUI_ACTION,
|
|
37
|
+
GUI_COMPARE,
|
|
38
|
+
GUI_DIRECTORY,
|
|
39
|
+
GUI_DISPLAY,
|
|
40
|
+
GUI_ENTRY,
|
|
41
|
+
GUI_HALT,
|
|
42
|
+
GUI_MAP,
|
|
43
|
+
GUI_MSG,
|
|
44
|
+
GUI_OPENFILE,
|
|
45
|
+
GUI_PAUSE,
|
|
46
|
+
GUI_SAVEFILE,
|
|
47
|
+
GUI_SELECTROWS,
|
|
48
|
+
GuiSpec,
|
|
49
|
+
QUERY_CONSOLE,
|
|
50
|
+
enable_gui,
|
|
51
|
+
get_yn,
|
|
52
|
+
get_yn_win,
|
|
53
|
+
gui_connect,
|
|
54
|
+
gui_credentials,
|
|
55
|
+
pause,
|
|
56
|
+
pause_win,
|
|
57
|
+
)
|
|
58
|
+
from execsql.utils.strings import unquoted
|
|
28
59
|
|
|
29
60
|
|
|
30
61
|
def x_prompt(**kwargs: Any) -> None:
|
|
@@ -32,13 +63,13 @@ def x_prompt(**kwargs: Any) -> None:
|
|
|
32
63
|
schema = kwargs["schema"]
|
|
33
64
|
table = kwargs["table"]
|
|
34
65
|
message = kwargs["message"]
|
|
35
|
-
help_url =
|
|
66
|
+
help_url = unquoted(kwargs["help"])
|
|
36
67
|
free = kwargs["free"] is not None
|
|
37
68
|
sq_name = db.schema_qualified_table_name(schema, table)
|
|
38
|
-
script, line_no =
|
|
69
|
+
script, line_no = current_script_line()
|
|
39
70
|
cmd = f"select * from {sq_name};"
|
|
40
71
|
colnames, rows = db.select_data(cmd)
|
|
41
|
-
|
|
72
|
+
enable_gui()
|
|
42
73
|
return_queue = _queue.Queue()
|
|
43
74
|
gui_args = {
|
|
44
75
|
"title": table,
|
|
@@ -49,15 +80,14 @@ def x_prompt(**kwargs: Any) -> None:
|
|
|
49
80
|
"help_url": help_url,
|
|
50
81
|
"free": free,
|
|
51
82
|
}
|
|
52
|
-
_state.gui_manager_queue.put(
|
|
83
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_DISPLAY, gui_args, return_queue))
|
|
53
84
|
if not free:
|
|
54
85
|
user_response = return_queue.get(block=True)
|
|
55
86
|
btn = user_response["button"]
|
|
56
|
-
if not btn:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
_state.exit_now(2, None)
|
|
87
|
+
if not btn and _state.status.cancel_halt:
|
|
88
|
+
msg = f"Halted from display of {sq_name}"
|
|
89
|
+
_state.exec_log.log_exit_halt(script, line_no, msg)
|
|
90
|
+
exit_now(2, None)
|
|
61
91
|
return None
|
|
62
92
|
|
|
63
93
|
|
|
@@ -70,14 +100,14 @@ def x_prompt_enter(**kwargs: Any) -> None:
|
|
|
70
100
|
schema = kwargs["schema"]
|
|
71
101
|
table = kwargs["table"]
|
|
72
102
|
initial = kwargs["initial"]
|
|
73
|
-
help_url =
|
|
103
|
+
help_url = unquoted(kwargs["help"])
|
|
74
104
|
if table is not None:
|
|
75
105
|
db = _state.dbs.current()
|
|
76
106
|
cmd = f"select * from {db.schema_qualified_table_name(schema, table)};"
|
|
77
107
|
hdrs, rows = db.select_data(cmd)
|
|
78
108
|
else:
|
|
79
109
|
hdrs, rows = None, None
|
|
80
|
-
|
|
110
|
+
enable_gui()
|
|
81
111
|
return_queue = _queue.Queue()
|
|
82
112
|
gui_args = {
|
|
83
113
|
"title": "Enter a value",
|
|
@@ -93,18 +123,18 @@ def x_prompt_enter(**kwargs: Any) -> None:
|
|
|
93
123
|
"help_url": help_url,
|
|
94
124
|
"free": False,
|
|
95
125
|
}
|
|
96
|
-
_state.gui_manager_queue.put(
|
|
126
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_DISPLAY, gui_args, return_queue))
|
|
97
127
|
user_response = return_queue.get(block=True)
|
|
98
128
|
btnval = user_response["button"]
|
|
99
129
|
txtval = user_response["return_value"]
|
|
100
130
|
if btnval is None:
|
|
101
131
|
if _state.status.cancel_halt:
|
|
102
|
-
_state.exec_log.log_exit_halt(*
|
|
103
|
-
|
|
132
|
+
_state.exec_log.log_exit_halt(*current_script_line(), msg="Quit from prompt to enter a SUB value.")
|
|
133
|
+
exit_now(2, None)
|
|
104
134
|
else:
|
|
105
135
|
subvarset = _state.subvars if sub_var[0] != "~" else _state.commandliststack[-1].localvars
|
|
106
136
|
subvarset.add_substitution(sub_var, txtval)
|
|
107
|
-
script_name, lno =
|
|
137
|
+
script_name, lno = current_script_line()
|
|
108
138
|
if as_pw:
|
|
109
139
|
_state.exec_log.log_status_info(f"Password assigned to variable {{{sub_var}}} on line {lno}.")
|
|
110
140
|
else:
|
|
@@ -120,17 +150,17 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
120
150
|
display_schema = kwargs["schemadisp"]
|
|
121
151
|
display_table = kwargs["tabledisp"]
|
|
122
152
|
message = kwargs["message"]
|
|
123
|
-
help_url =
|
|
153
|
+
help_url = unquoted(kwargs["help"])
|
|
124
154
|
tbl1 = _state.dbs.current().schema_qualified_table_name(spec_schema, spec_table)
|
|
125
155
|
try:
|
|
126
156
|
if not _state.dbs.current().table_exists(spec_table, spec_schema):
|
|
127
|
-
raise
|
|
157
|
+
raise ErrInfo(
|
|
128
158
|
type="cmd",
|
|
129
159
|
command_text=kwargs["metacommandline"],
|
|
130
160
|
other_msg=f"Table {spec_table} does not exist",
|
|
131
161
|
)
|
|
132
162
|
except Exception:
|
|
133
|
-
pass
|
|
163
|
+
pass # Best-effort check; some adapters lack information_schema.
|
|
134
164
|
curs = _state.dbs.current().cursor()
|
|
135
165
|
cmd = f"select * from {tbl1};"
|
|
136
166
|
curs.execute(cmd)
|
|
@@ -139,7 +169,7 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
139
169
|
cmd = f"select * from {tbl1} order by sequence;"
|
|
140
170
|
curs.execute(cmd)
|
|
141
171
|
if not ("sub_var" in colhdrs and "prompt" in colhdrs):
|
|
142
|
-
raise
|
|
172
|
+
raise ErrInfo(
|
|
143
173
|
type="cmd",
|
|
144
174
|
command_text=kwargs["metacommandline"],
|
|
145
175
|
other_msg="The variable name and prompt are required, but missing.",
|
|
@@ -155,20 +185,20 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
155
185
|
v = dict(zip(colhdrs, r))
|
|
156
186
|
subvar = v.get("sub_var")
|
|
157
187
|
if not subvar:
|
|
158
|
-
raise
|
|
188
|
+
raise ErrInfo(
|
|
159
189
|
type="cmd",
|
|
160
190
|
command_text=kwargs["metacommandline"],
|
|
161
191
|
other_msg="A substitution variable name must be provided for all of the entry specifications.",
|
|
162
192
|
)
|
|
163
193
|
if not subvar_rx.match(subvar):
|
|
164
|
-
raise
|
|
194
|
+
raise ErrInfo(
|
|
165
195
|
type="cmd",
|
|
166
196
|
command_text=kwargs["metacommandline"],
|
|
167
197
|
other_msg=f"Invalid substitution variable name: {subvar}",
|
|
168
198
|
)
|
|
169
199
|
prompt_msg = v.get("prompt")
|
|
170
200
|
if not prompt_msg:
|
|
171
|
-
raise
|
|
201
|
+
raise ErrInfo(
|
|
172
202
|
type="cmd",
|
|
173
203
|
command_text=kwargs["metacommandline"],
|
|
174
204
|
other_msg="A prompt must be provided for all of the entry specifications.",
|
|
@@ -181,7 +211,7 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
181
211
|
else:
|
|
182
212
|
initial_value = str(v["initial_value"])
|
|
183
213
|
except Exception:
|
|
184
|
-
raise
|
|
214
|
+
raise ErrInfo(
|
|
185
215
|
type="cmd",
|
|
186
216
|
command_text=kwargs["metacommandline"],
|
|
187
217
|
other_msg=f"The initial value of {v['initial_value']} can't be used.",
|
|
@@ -197,7 +227,7 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
197
227
|
try:
|
|
198
228
|
entry_width = int(entry_width)
|
|
199
229
|
except Exception:
|
|
200
|
-
raise
|
|
230
|
+
raise ErrInfo(
|
|
201
231
|
type="cmd",
|
|
202
232
|
command_text=kwargs["metacommandline"],
|
|
203
233
|
other_msg=f"Entry width {entry_width} is not an integer",
|
|
@@ -208,7 +238,7 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
208
238
|
try:
|
|
209
239
|
entry_height = int(entry_height)
|
|
210
240
|
except Exception:
|
|
211
|
-
raise
|
|
241
|
+
raise ErrInfo(
|
|
212
242
|
type="cmd",
|
|
213
243
|
command_text=kwargs["metacommandline"],
|
|
214
244
|
other_msg=f"Entry height {entry_height} is not an integer",
|
|
@@ -221,7 +251,7 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
221
251
|
try:
|
|
222
252
|
entry_col = int(entry_col)
|
|
223
253
|
except Exception:
|
|
224
|
-
raise
|
|
254
|
+
raise ErrInfo(
|
|
225
255
|
type="cmd",
|
|
226
256
|
command_text=kwargs["metacommandline"],
|
|
227
257
|
other_msg=f"Entry column {entry_col} is not an integer",
|
|
@@ -231,7 +261,7 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
231
261
|
subvarset = _state.subvars if subvar[0] != "~" else _state.commandliststack[-1].localvars
|
|
232
262
|
subvarset.remove_substitution(subvar)
|
|
233
263
|
entry_list.append(
|
|
234
|
-
|
|
264
|
+
EntrySpec(
|
|
235
265
|
subvar,
|
|
236
266
|
prompt_msg,
|
|
237
267
|
required=bool(v.get("required")),
|
|
@@ -250,7 +280,7 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
250
280
|
db = _state.dbs.current()
|
|
251
281
|
sq_name = db.schema_qualified_table_name(display_schema, display_table)
|
|
252
282
|
colnames, rows = db.select_data(f"select * from {sq_name};")
|
|
253
|
-
|
|
283
|
+
enable_gui()
|
|
254
284
|
return_queue = _queue.Queue()
|
|
255
285
|
gui_args = {
|
|
256
286
|
"title": "Entry",
|
|
@@ -260,11 +290,11 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
260
290
|
"rowset": rows,
|
|
261
291
|
"help_url": help_url,
|
|
262
292
|
}
|
|
263
|
-
_state.gui_manager_queue.put(
|
|
293
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_ENTRY, gui_args, return_queue))
|
|
264
294
|
user_response = return_queue.get(block=True)
|
|
265
295
|
btn = user_response["button"]
|
|
266
296
|
entries = user_response["return_value"]
|
|
267
|
-
script, line_no =
|
|
297
|
+
script, line_no = current_script_line()
|
|
268
298
|
if btn:
|
|
269
299
|
for e in entries:
|
|
270
300
|
if e.value:
|
|
@@ -283,7 +313,7 @@ def x_prompt_entryform(**kwargs: Any) -> None:
|
|
|
283
313
|
if _state.status.cancel_halt:
|
|
284
314
|
msg = f"Halted from entry form {tbl1}"
|
|
285
315
|
_state.exec_log.log_exit_halt(script, line_no, msg)
|
|
286
|
-
|
|
316
|
+
exit_now(2, None)
|
|
287
317
|
|
|
288
318
|
|
|
289
319
|
def x_prompt_pause(**kwargs: Any) -> None:
|
|
@@ -301,20 +331,20 @@ def x_prompt_pause(**kwargs: Any) -> None:
|
|
|
301
331
|
maxtime_secs = countdown
|
|
302
332
|
if timeunit and timeunit.lower() == "minutes":
|
|
303
333
|
maxtime_secs = maxtime_secs * 60
|
|
304
|
-
|
|
334
|
+
enable_gui()
|
|
305
335
|
return_queue = _queue.Queue()
|
|
306
336
|
gui_args = {
|
|
307
|
-
"title": f"Script {
|
|
337
|
+
"title": f"Script {current_script_line()[0]}",
|
|
308
338
|
"message": msg,
|
|
309
339
|
"countdown": maxtime_secs,
|
|
310
340
|
}
|
|
311
|
-
_state.gui_manager_queue.put(
|
|
341
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_PAUSE, gui_args, return_queue))
|
|
312
342
|
user_response = return_queue.get(block=True)
|
|
313
343
|
quit = user_response["quit"]
|
|
314
344
|
return_queue.task_done()
|
|
315
345
|
if quit and _state.status.cancel_halt:
|
|
316
|
-
_state.exec_log.log_exit_halt(*
|
|
317
|
-
|
|
346
|
+
_state.exec_log.log_exit_halt(*current_script_line(), msg=quitmsg)
|
|
347
|
+
exit_now(2, None)
|
|
318
348
|
return None
|
|
319
349
|
|
|
320
350
|
|
|
@@ -328,20 +358,20 @@ def prompt_compare(button_list: list, **kwargs: Any) -> Any:
|
|
|
328
358
|
alias2 = kwargs["alias2"]
|
|
329
359
|
pks = kwargs["pks"]
|
|
330
360
|
msg = kwargs["msg"]
|
|
331
|
-
help_url =
|
|
361
|
+
help_url = unquoted(kwargs["help"])
|
|
332
362
|
badaliasmsg = "Alias %s is not recognized."
|
|
333
363
|
if alias1 is not None:
|
|
334
364
|
try:
|
|
335
365
|
db1 = _state.dbs.aliased_as(alias1)
|
|
336
366
|
except Exception:
|
|
337
|
-
raise
|
|
367
|
+
raise ErrInfo(type="error", other_msg=badaliasmsg % alias1)
|
|
338
368
|
else:
|
|
339
369
|
db1 = _state.dbs.current()
|
|
340
370
|
if alias2 is not None:
|
|
341
371
|
try:
|
|
342
372
|
db2 = _state.dbs.aliased_as(alias2)
|
|
343
373
|
except Exception:
|
|
344
|
-
raise
|
|
374
|
+
raise ErrInfo(type="error", other_msg=badaliasmsg % alias2)
|
|
345
375
|
else:
|
|
346
376
|
db2 = _state.dbs.current()
|
|
347
377
|
sq_name1 = db1.schema_qualified_table_name(schema1, table1)
|
|
@@ -350,19 +380,19 @@ def prompt_compare(button_list: list, **kwargs: Any) -> Any:
|
|
|
350
380
|
sql2 = f"select * from {sq_name2};"
|
|
351
381
|
hdrs1, rows1 = db1.select_data(sql1)
|
|
352
382
|
if len(rows1) == 0:
|
|
353
|
-
raise
|
|
383
|
+
raise ErrInfo("error", other_msg=f"There are no data in {sq_name1}.")
|
|
354
384
|
hdrs2, rows2 = db2.select_data(sql2)
|
|
355
385
|
if len(rows2) == 0:
|
|
356
|
-
raise
|
|
386
|
+
raise ErrInfo("error", other_msg=f"There are no data in {sq_name2}.")
|
|
357
387
|
pklist = [pk.replace('"', "").replace(" ", "") for pk in pks.split(",")]
|
|
358
388
|
sidebyside = orient.lower() == "beside"
|
|
359
|
-
if not all(
|
|
360
|
-
script, line_no =
|
|
361
|
-
raise
|
|
389
|
+
if not all(col in hdrs1 for col in pklist) or not all(col in hdrs2 for col in pklist):
|
|
390
|
+
script, line_no = current_script_line()
|
|
391
|
+
raise ErrInfo(
|
|
362
392
|
type="error",
|
|
363
393
|
other_msg=f"Specified primary key columns do not exist in PROMPT COMPARE metacommand on line {line_no} of {script}.",
|
|
364
394
|
)
|
|
365
|
-
|
|
395
|
+
enable_gui()
|
|
366
396
|
return_queue = _queue.Queue()
|
|
367
397
|
gui_args = {
|
|
368
398
|
"title": "Compare data",
|
|
@@ -376,15 +406,14 @@ def prompt_compare(button_list: list, **kwargs: Any) -> Any:
|
|
|
376
406
|
"sidebyside": sidebyside,
|
|
377
407
|
"help_url": help_url,
|
|
378
408
|
}
|
|
379
|
-
_state.gui_manager_queue.put(
|
|
409
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_COMPARE, gui_args, return_queue))
|
|
380
410
|
user_response = return_queue.get(block=True)
|
|
381
411
|
btn = user_response["button"]
|
|
382
|
-
if btn is None:
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
_state.exit_now(2, None)
|
|
412
|
+
if btn is None and _state.status.cancel_halt:
|
|
413
|
+
script, line_no = current_script_line()
|
|
414
|
+
msg = f"Halted from comparison of {sq_name1} and {sq_name2}"
|
|
415
|
+
_state.exec_log.log_exit_halt(script, line_no, msg)
|
|
416
|
+
exit_now(2, None)
|
|
388
417
|
return btn
|
|
389
418
|
|
|
390
419
|
|
|
@@ -394,12 +423,12 @@ def x_prompt_compare(**kwargs: Any) -> None:
|
|
|
394
423
|
|
|
395
424
|
def x_prompt_ask_compare(**kwargs: Any) -> None:
|
|
396
425
|
subvar = kwargs["match"]
|
|
397
|
-
script, lno =
|
|
426
|
+
script, lno = current_script_line()
|
|
398
427
|
btn = prompt_compare([("Yes", 1, "y"), ("No", 0, "n")], **kwargs)
|
|
399
428
|
if btn is None:
|
|
400
429
|
if _state.status.cancel_halt:
|
|
401
430
|
_state.exec_log.log_exit_halt(script, lno, msg="Quit from PROMPT ASK COMPARE metacommand")
|
|
402
|
-
|
|
431
|
+
exit_now(2, None)
|
|
403
432
|
else:
|
|
404
433
|
respstr = "Yes" if btn == 1 else "No"
|
|
405
434
|
subvarset = _state.subvars if subvar[0] != "~" else _state.commandliststack[-1].localvars
|
|
@@ -412,15 +441,15 @@ def x_prompt_ask(**kwargs: Any) -> None:
|
|
|
412
441
|
subvar = kwargs["match"]
|
|
413
442
|
schema = kwargs["schema"]
|
|
414
443
|
table = kwargs["table"]
|
|
415
|
-
help_url =
|
|
416
|
-
script, lno =
|
|
444
|
+
help_url = unquoted(kwargs["help"])
|
|
445
|
+
script, lno = current_script_line()
|
|
417
446
|
if table is not None:
|
|
418
447
|
queryname = _state.dbs.current().schema_qualified_table_name(schema, table)
|
|
419
448
|
cmd = f"select * from {queryname};"
|
|
420
449
|
colnames, rows = _state.dbs.current().select_data(cmd)
|
|
421
450
|
else:
|
|
422
451
|
colnames, rows = None, None
|
|
423
|
-
|
|
452
|
+
enable_gui()
|
|
424
453
|
return_queue = _queue.Queue()
|
|
425
454
|
gui_args = {
|
|
426
455
|
"title": script,
|
|
@@ -430,13 +459,13 @@ def x_prompt_ask(**kwargs: Any) -> None:
|
|
|
430
459
|
"rowset": rows,
|
|
431
460
|
"help_url": help_url,
|
|
432
461
|
}
|
|
433
|
-
_state.gui_manager_queue.put(
|
|
462
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_DISPLAY, gui_args, return_queue))
|
|
434
463
|
user_response = return_queue.get(block=True)
|
|
435
464
|
btn = user_response["button"]
|
|
436
465
|
if btn is None:
|
|
437
466
|
if _state.status.cancel_halt:
|
|
438
467
|
_state.exec_log.log_exit_halt(script, lno, msg=quitmsg)
|
|
439
|
-
|
|
468
|
+
exit_now(2, None)
|
|
440
469
|
else:
|
|
441
470
|
respstr = "Yes" if btn == 1 else "No"
|
|
442
471
|
subvarset = _state.subvars if subvar[0] != "~" else _state.commandliststack[-1].localvars
|
|
@@ -458,10 +487,10 @@ def x_prompt_map(**kwargs: Any) -> None:
|
|
|
458
487
|
symbol_col = kwargs["symbol_col"]
|
|
459
488
|
color_col = kwargs["color_col"]
|
|
460
489
|
sq_name = db.schema_qualified_table_name(schema, table)
|
|
461
|
-
script, line_no =
|
|
490
|
+
script, line_no = current_script_line()
|
|
462
491
|
cmd = f"select * from {sq_name};"
|
|
463
492
|
colnames, rows = db.select_data(cmd)
|
|
464
|
-
|
|
493
|
+
enable_gui()
|
|
465
494
|
return_queue = _queue.Queue()
|
|
466
495
|
gui_args = {
|
|
467
496
|
"title": table,
|
|
@@ -475,14 +504,13 @@ def x_prompt_map(**kwargs: Any) -> None:
|
|
|
475
504
|
"symbol_col": symbol_col,
|
|
476
505
|
"color_col": color_col,
|
|
477
506
|
}
|
|
478
|
-
_state.gui_manager_queue.put(
|
|
507
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_MAP, gui_args, return_queue))
|
|
479
508
|
user_response = return_queue.get(block=True)
|
|
480
509
|
btn = user_response["button"]
|
|
481
|
-
if not btn:
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
_state.exit_now(2, None)
|
|
510
|
+
if not btn and _state.status.cancel_halt:
|
|
511
|
+
msg = f"Halted from map of {sq_name}"
|
|
512
|
+
_state.exec_log.log_exit_halt(script, line_no, msg)
|
|
513
|
+
exit_now(2, None)
|
|
486
514
|
return None
|
|
487
515
|
|
|
488
516
|
|
|
@@ -493,7 +521,7 @@ def x_prompt_action(**kwargs: Any) -> None:
|
|
|
493
521
|
display_table = kwargs["tabledisp"]
|
|
494
522
|
message = kwargs["message"]
|
|
495
523
|
compact = kwargs["compact"]
|
|
496
|
-
help_url =
|
|
524
|
+
help_url = unquoted(kwargs["help"])
|
|
497
525
|
if compact is not None:
|
|
498
526
|
compact = int(compact)
|
|
499
527
|
do_continue = kwargs["continue"]
|
|
@@ -502,13 +530,13 @@ def x_prompt_action(**kwargs: Any) -> None:
|
|
|
502
530
|
tbl1 = _state.dbs.current().schema_qualified_table_name(spec_schema, spec_table)
|
|
503
531
|
try:
|
|
504
532
|
if not _state.dbs.current().table_exists(spec_table, spec_schema):
|
|
505
|
-
raise
|
|
533
|
+
raise ErrInfo(
|
|
506
534
|
type="cmd",
|
|
507
535
|
command_text=kwargs["metacommandline"],
|
|
508
536
|
other_msg=f"Table {spec_table} does not exist",
|
|
509
537
|
)
|
|
510
538
|
except Exception:
|
|
511
|
-
pass
|
|
539
|
+
pass # Best-effort check; some adapters lack information_schema.
|
|
512
540
|
curs = _state.dbs.current().cursor()
|
|
513
541
|
cmd = f"select * from {tbl1};"
|
|
514
542
|
curs.execute(cmd)
|
|
@@ -517,7 +545,7 @@ def x_prompt_action(**kwargs: Any) -> None:
|
|
|
517
545
|
cmd = f"select * from {tbl1} order by sequence;"
|
|
518
546
|
curs.execute(cmd)
|
|
519
547
|
if not ("label" in colhdrs and "prompt" in colhdrs and "script" in colhdrs):
|
|
520
|
-
raise
|
|
548
|
+
raise ErrInfo(
|
|
521
549
|
type="cmd",
|
|
522
550
|
command_text=kwargs["metacommandline"],
|
|
523
551
|
other_msg="The columns 'label', 'prompt', and 'script' are required, but one or more is missing.",
|
|
@@ -528,20 +556,20 @@ def x_prompt_action(**kwargs: Any) -> None:
|
|
|
528
556
|
v = dict(zip(colhdrs, r))
|
|
529
557
|
button_label = v.get("label")
|
|
530
558
|
if not button_label:
|
|
531
|
-
raise
|
|
559
|
+
raise ErrInfo(
|
|
532
560
|
type="cmd",
|
|
533
561
|
command_text=kwargs["metacommandline"],
|
|
534
562
|
other_msg="A button label must be provided for all of the action specifications.",
|
|
535
563
|
)
|
|
536
564
|
prompt_msg = v.get("prompt")
|
|
537
565
|
if not prompt_msg:
|
|
538
|
-
raise
|
|
566
|
+
raise ErrInfo(
|
|
539
567
|
type="cmd",
|
|
540
568
|
command_text=kwargs["metacommandline"],
|
|
541
569
|
other_msg="A prompt must be provided for all of the action specifications.",
|
|
542
570
|
)
|
|
543
571
|
action_list.append(
|
|
544
|
-
|
|
572
|
+
ActionSpec(
|
|
545
573
|
button_label,
|
|
546
574
|
prompt_msg,
|
|
547
575
|
v["script"],
|
|
@@ -553,7 +581,7 @@ def x_prompt_action(**kwargs: Any) -> None:
|
|
|
553
581
|
db = _state.dbs.current()
|
|
554
582
|
sq_name = db.schema_qualified_table_name(display_schema, display_table)
|
|
555
583
|
colnames, rows = db.select_data(f"select * from {sq_name};")
|
|
556
|
-
|
|
584
|
+
enable_gui()
|
|
557
585
|
return_queue = _queue.Queue()
|
|
558
586
|
gui_args = {
|
|
559
587
|
"title": "Actions",
|
|
@@ -565,15 +593,14 @@ def x_prompt_action(**kwargs: Any) -> None:
|
|
|
565
593
|
"column_headers": colnames,
|
|
566
594
|
"rowset": rows,
|
|
567
595
|
}
|
|
568
|
-
_state.gui_manager_queue.put(
|
|
596
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_ACTION, gui_args, return_queue))
|
|
569
597
|
user_response = return_queue.get(block=True)
|
|
570
598
|
btn = user_response["button"]
|
|
571
|
-
script, line_no =
|
|
572
|
-
if not btn:
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
_state.exit_now(2, None)
|
|
599
|
+
script, line_no = current_script_line()
|
|
600
|
+
if not btn and _state.status.cancel_halt:
|
|
601
|
+
msg = f"Halted from entry form {tbl1}"
|
|
602
|
+
_state.exec_log.log_exit_halt(script, line_no, msg)
|
|
603
|
+
exit_now(2, None)
|
|
577
604
|
|
|
578
605
|
|
|
579
606
|
def x_prompt_savefile(**kwargs: Any) -> None:
|
|
@@ -586,19 +613,19 @@ def x_prompt_savefile(**kwargs: Any) -> None:
|
|
|
586
613
|
try:
|
|
587
614
|
subvarset = _state.subvars if sub_name[0] != "~" else _state.commandliststack[-1].localvars
|
|
588
615
|
subvarset.remove_substitution(sub_name)
|
|
589
|
-
script, lno =
|
|
590
|
-
working_dir = startdir if startdir is not None else
|
|
591
|
-
|
|
616
|
+
script, lno = current_script_line()
|
|
617
|
+
working_dir = startdir if startdir is not None else str(Path(script).resolve().parent)
|
|
618
|
+
enable_gui()
|
|
592
619
|
return_queue = _queue.Queue()
|
|
593
620
|
gui_args = {"working_dir": working_dir, "script": script}
|
|
594
|
-
_state.gui_manager_queue.put(
|
|
621
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_SAVEFILE, gui_args, return_queue))
|
|
595
622
|
user_response = return_queue.get(block=True)
|
|
596
623
|
fn = user_response["filename"]
|
|
597
624
|
if not fn:
|
|
598
625
|
if _state.status.cancel_halt:
|
|
599
626
|
msg = "Halted from prompt for name of file to save"
|
|
600
627
|
_state.exec_log.log_exit_halt(script, lno, msg)
|
|
601
|
-
|
|
628
|
+
exit_now(2, None)
|
|
602
629
|
else:
|
|
603
630
|
if os.name != "posix":
|
|
604
631
|
fn = fn.replace("/", "\\")
|
|
@@ -609,7 +636,7 @@ def x_prompt_savefile(**kwargs: Any) -> None:
|
|
|
609
636
|
if sub_name2 is not None:
|
|
610
637
|
subvarset2 = _state.subvars if sub_name2[0] != "~" else _state.commandliststack[-1].localvars
|
|
611
638
|
subvarset2.remove_substitution(sub_name2)
|
|
612
|
-
basefn =
|
|
639
|
+
basefn = Path(fn).name
|
|
613
640
|
subvarset2.add_substitution(sub_name2, basefn)
|
|
614
641
|
_state.exec_log.log_status_info(
|
|
615
642
|
f"Substitution variable {sub_name2} set to filename {basefn} at line {lno} of {script}",
|
|
@@ -617,7 +644,7 @@ def x_prompt_savefile(**kwargs: Any) -> None:
|
|
|
617
644
|
if sub_name3 is not None:
|
|
618
645
|
subvarset3 = _state.subvars if sub_name3[0] != "~" else _state.commandliststack[-1].localvars
|
|
619
646
|
subvarset3.remove_substitution(sub_name3)
|
|
620
|
-
dirname =
|
|
647
|
+
dirname = str(Path(fn).parent)
|
|
621
648
|
if os.name != "posix":
|
|
622
649
|
dirname = dirname.replace("/", "\\")
|
|
623
650
|
subvarset3.add_substitution(sub_name3, dirname)
|
|
@@ -627,7 +654,7 @@ def x_prompt_savefile(**kwargs: Any) -> None:
|
|
|
627
654
|
if sub_name4 is not None:
|
|
628
655
|
subvarset4 = _state.subvars if sub_name4[0] != "~" else _state.commandliststack[-1].localvars
|
|
629
656
|
subvarset4.remove_substitution(sub_name4)
|
|
630
|
-
|
|
657
|
+
ext = Path(fn).suffix
|
|
631
658
|
if ext is None:
|
|
632
659
|
subvarset4.add_substitution(sub_name4, "")
|
|
633
660
|
else:
|
|
@@ -636,13 +663,11 @@ def x_prompt_savefile(**kwargs: Any) -> None:
|
|
|
636
663
|
if sub_name5 is not None:
|
|
637
664
|
subvarset5 = _state.subvars if sub_name5[0] != "~" else _state.commandliststack[-1].localvars
|
|
638
665
|
subvarset5.remove_substitution(sub_name5)
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
subvarset5.add_substitution(sub_name5, root)
|
|
642
|
-
except (_state.ErrInfo, SystemExit):
|
|
666
|
+
subvarset5.add_substitution(sub_name5, Path(fn).stem)
|
|
667
|
+
except (ErrInfo, SystemExit):
|
|
643
668
|
raise
|
|
644
669
|
except Exception:
|
|
645
|
-
raise
|
|
670
|
+
raise ErrInfo(type="exception", exception_msg=exception_desc())
|
|
646
671
|
return None
|
|
647
672
|
|
|
648
673
|
|
|
@@ -654,26 +679,26 @@ def x_prompt_openfile(**kwargs: Any) -> None:
|
|
|
654
679
|
sub_name5 = kwargs["fnbase_match"]
|
|
655
680
|
startdir = kwargs["startdir"]
|
|
656
681
|
if sub_name2 is not None and sub_name2 == sub_name:
|
|
657
|
-
raise
|
|
682
|
+
raise ErrInfo(
|
|
658
683
|
type="error",
|
|
659
684
|
other_msg="Different values can't be assigned to the same substitution variable.",
|
|
660
685
|
)
|
|
661
686
|
try:
|
|
662
687
|
subvarset = _state.subvars if sub_name[0] != "~" else _state.commandliststack[-1].localvars
|
|
663
688
|
subvarset.remove_substitution(sub_name)
|
|
664
|
-
script, lno =
|
|
665
|
-
working_dir = startdir if startdir is not None else
|
|
666
|
-
|
|
689
|
+
script, lno = current_script_line()
|
|
690
|
+
working_dir = startdir if startdir is not None else str(Path(script).resolve().parent)
|
|
691
|
+
enable_gui()
|
|
667
692
|
return_queue = _queue.Queue()
|
|
668
693
|
gui_args = {"working_dir": working_dir, "script": script}
|
|
669
|
-
_state.gui_manager_queue.put(
|
|
694
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_OPENFILE, gui_args, return_queue))
|
|
670
695
|
user_response = return_queue.get(block=True)
|
|
671
696
|
fn = user_response["filename"]
|
|
672
697
|
if not fn:
|
|
673
698
|
if _state.status.cancel_halt:
|
|
674
699
|
msg = "Halted from prompt for name of file to open"
|
|
675
700
|
_state.exec_log.log_exit_halt(script, lno, msg)
|
|
676
|
-
|
|
701
|
+
exit_now(2, None)
|
|
677
702
|
else:
|
|
678
703
|
if os.name != "posix":
|
|
679
704
|
fn = fn.replace("/", "\\")
|
|
@@ -684,19 +709,19 @@ def x_prompt_openfile(**kwargs: Any) -> None:
|
|
|
684
709
|
if sub_name2 is not None:
|
|
685
710
|
subvarset2 = _state.subvars if sub_name2[0] != "~" else _state.commandliststack[-1].localvars
|
|
686
711
|
subvarset2.remove_substitution(sub_name2)
|
|
687
|
-
basefn =
|
|
712
|
+
basefn = Path(fn).name
|
|
688
713
|
subvarset2.add_substitution(sub_name2, basefn)
|
|
689
714
|
if sub_name3 is not None:
|
|
690
715
|
subvarset3 = _state.subvars if sub_name3[0] != "~" else _state.commandliststack[-1].localvars
|
|
691
716
|
subvarset3.remove_substitution(sub_name3)
|
|
692
|
-
dirname =
|
|
717
|
+
dirname = str(Path(fn).parent)
|
|
693
718
|
if os.name != "posix":
|
|
694
719
|
dirname = dirname.replace("/", "\\")
|
|
695
720
|
subvarset3.add_substitution(sub_name3, dirname)
|
|
696
721
|
if sub_name4 is not None:
|
|
697
722
|
subvarset4 = _state.subvars if sub_name4[0] != "~" else _state.commandliststack[-1].localvars
|
|
698
723
|
subvarset4.remove_substitution(sub_name4)
|
|
699
|
-
|
|
724
|
+
ext = Path(fn).suffix
|
|
700
725
|
if ext is None:
|
|
701
726
|
subvarset4.add_substitution(sub_name4, "")
|
|
702
727
|
else:
|
|
@@ -705,13 +730,11 @@ def x_prompt_openfile(**kwargs: Any) -> None:
|
|
|
705
730
|
if sub_name5 is not None:
|
|
706
731
|
subvarset5 = _state.subvars if sub_name5[0] != "~" else _state.commandliststack[-1].localvars
|
|
707
732
|
subvarset5.remove_substitution(sub_name5)
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
subvarset5.add_substitution(sub_name5, root)
|
|
711
|
-
except (_state.ErrInfo, SystemExit):
|
|
733
|
+
subvarset5.add_substitution(sub_name5, Path(fn).stem)
|
|
734
|
+
except (ErrInfo, SystemExit):
|
|
712
735
|
raise
|
|
713
736
|
except Exception:
|
|
714
|
-
raise
|
|
737
|
+
raise ErrInfo(type="exception", exception_msg=exception_desc())
|
|
715
738
|
return None
|
|
716
739
|
|
|
717
740
|
|
|
@@ -722,32 +745,32 @@ def x_prompt_directory(**kwargs: Any) -> None:
|
|
|
722
745
|
try:
|
|
723
746
|
subvarset = _state.subvars if sub_name[0] != "~" else _state.commandliststack[-1].localvars
|
|
724
747
|
subvarset.remove_substitution(sub_name)
|
|
725
|
-
script, lno =
|
|
726
|
-
working_dir = startdir if startdir is not None else
|
|
727
|
-
|
|
748
|
+
script, lno = current_script_line()
|
|
749
|
+
working_dir = startdir if startdir is not None else str(Path(script).resolve().parent)
|
|
750
|
+
enable_gui()
|
|
728
751
|
return_queue = _queue.Queue()
|
|
729
752
|
gui_args = {"working_dir": working_dir, "script": script}
|
|
730
|
-
_state.gui_manager_queue.put(
|
|
753
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_DIRECTORY, gui_args, return_queue))
|
|
731
754
|
user_response = return_queue.get(block=True)
|
|
732
755
|
dirname = user_response["directory"]
|
|
733
756
|
if not dirname:
|
|
734
757
|
if _state.status.cancel_halt:
|
|
735
758
|
msg = "Halted from prompt for name of directory"
|
|
736
759
|
_state.exec_log.log_exit_halt(script, lno, msg)
|
|
737
|
-
|
|
760
|
+
exit_now(2, None)
|
|
738
761
|
else:
|
|
739
762
|
if fullpath is not None:
|
|
740
|
-
dirname =
|
|
763
|
+
dirname = str(Path(dirname).resolve())
|
|
741
764
|
if os.name != "posix":
|
|
742
765
|
dirname = dirname.replace("/", "\\")
|
|
743
766
|
subvarset.add_substitution(sub_name, dirname)
|
|
744
767
|
_state.exec_log.log_status_info(
|
|
745
768
|
f"Substitution string {sub_name} set to directory {dirname} at line {lno} of {script}",
|
|
746
769
|
)
|
|
747
|
-
except (
|
|
770
|
+
except (ErrInfo, SystemExit):
|
|
748
771
|
raise
|
|
749
772
|
except Exception:
|
|
750
|
-
raise
|
|
773
|
+
raise ErrInfo(type="exception", exception_msg=exception_desc())
|
|
751
774
|
return None
|
|
752
775
|
|
|
753
776
|
|
|
@@ -759,20 +782,20 @@ def prompt_select_rows(button_list: list, **kwargs: Any) -> Any:
|
|
|
759
782
|
table2 = kwargs["table2"]
|
|
760
783
|
alias2 = kwargs["alias2"]
|
|
761
784
|
msg = kwargs["msg"]
|
|
762
|
-
help_url =
|
|
785
|
+
help_url = unquoted(kwargs["help"])
|
|
763
786
|
badaliasmsg = "Alias %s is not recognized."
|
|
764
787
|
if alias1 is not None:
|
|
765
788
|
try:
|
|
766
789
|
db1 = _state.dbs.aliased_as(alias1)
|
|
767
790
|
except Exception:
|
|
768
|
-
raise
|
|
791
|
+
raise ErrInfo(type="error", other_msg=badaliasmsg % alias1)
|
|
769
792
|
else:
|
|
770
793
|
db1 = _state.dbs.current()
|
|
771
794
|
if alias2 is not None:
|
|
772
795
|
try:
|
|
773
796
|
db2 = _state.dbs.aliased_as(alias2)
|
|
774
797
|
except Exception:
|
|
775
|
-
raise
|
|
798
|
+
raise ErrInfo(type="error", other_msg=badaliasmsg % alias2)
|
|
776
799
|
else:
|
|
777
800
|
db2 = _state.dbs.current()
|
|
778
801
|
sq_name1 = db1.schema_qualified_table_name(schema1, table1)
|
|
@@ -781,12 +804,12 @@ def prompt_select_rows(button_list: list, **kwargs: Any) -> Any:
|
|
|
781
804
|
sql2 = f"select * from {sq_name2};"
|
|
782
805
|
hdrs1, rows1 = db1.select_data(sql1)
|
|
783
806
|
if len(rows1) == 0:
|
|
784
|
-
raise
|
|
807
|
+
raise ErrInfo("error", other_msg=f"There are no data in {sq_name1}.")
|
|
785
808
|
hdrs2, rows2 = db2.select_data(sql2)
|
|
786
809
|
missing_hdrs = [hdr for hdr in hdrs1 if hdr not in hdrs2]
|
|
787
810
|
if len(missing_hdrs) > 0:
|
|
788
|
-
raise
|
|
789
|
-
|
|
811
|
+
raise ErrInfo("error", other_msg=f"Columns [{', '.join(missing_hdrs)}] are missing from {sq_name2}.")
|
|
812
|
+
enable_gui()
|
|
790
813
|
return_queue = _queue.Queue()
|
|
791
814
|
gui_args = {
|
|
792
815
|
"title": "Select rows",
|
|
@@ -800,15 +823,14 @@ def prompt_select_rows(button_list: list, **kwargs: Any) -> Any:
|
|
|
800
823
|
"table2": sq_name2,
|
|
801
824
|
"help_url": help_url,
|
|
802
825
|
}
|
|
803
|
-
_state.gui_manager_queue.put(
|
|
826
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_SELECTROWS, gui_args, return_queue))
|
|
804
827
|
user_response = return_queue.get(block=True)
|
|
805
828
|
btn = user_response["button"]
|
|
806
|
-
if btn is None:
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
_state.exit_now(2, None)
|
|
829
|
+
if btn is None and _state.status.cancel_halt:
|
|
830
|
+
script, line_no = current_script_line()
|
|
831
|
+
msg = f"Halted from selection of rows from {sq_name1} into {sq_name2}"
|
|
832
|
+
_state.exec_log.log_exit_halt(script, line_no, msg)
|
|
833
|
+
exit_now(2, None)
|
|
812
834
|
return btn
|
|
813
835
|
|
|
814
836
|
|
|
@@ -820,22 +842,22 @@ def x_prompt_credentials(**kwargs: Any) -> None:
|
|
|
820
842
|
message = kwargs["message"]
|
|
821
843
|
user = kwargs["user"]
|
|
822
844
|
pw = kwargs["pw"]
|
|
823
|
-
|
|
845
|
+
gui_credentials(message, username=user, pwtext=pw, cmd=kwargs["metacommandline"])
|
|
824
846
|
return None
|
|
825
847
|
|
|
826
848
|
|
|
827
849
|
def x_prompt_connect(**kwargs: Any) -> None:
|
|
828
850
|
alias = kwargs["alias"]
|
|
829
851
|
message = kwargs["message"]
|
|
830
|
-
help_url =
|
|
831
|
-
|
|
852
|
+
help_url = unquoted(kwargs["help"])
|
|
853
|
+
gui_connect(alias, message, help_url=help_url, cmd=kwargs["metacommandline"])
|
|
832
854
|
return None
|
|
833
855
|
|
|
834
856
|
|
|
835
857
|
def x_ask(**kwargs: Any) -> None:
|
|
836
858
|
message = kwargs["question"]
|
|
837
859
|
subvar = kwargs["match"]
|
|
838
|
-
script, lno =
|
|
860
|
+
script, lno = current_script_line()
|
|
839
861
|
if _state.gui_console:
|
|
840
862
|
return_queue = _queue.Queue()
|
|
841
863
|
gui_args = {
|
|
@@ -844,23 +866,23 @@ def x_ask(**kwargs: Any) -> None:
|
|
|
844
866
|
"button_list": [("Yes", 1, "y"), ("No", 0, "n")],
|
|
845
867
|
"free": False,
|
|
846
868
|
}
|
|
847
|
-
_state.gui_manager_queue.put(
|
|
869
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_DISPLAY, gui_args, return_queue))
|
|
848
870
|
user_response = return_queue.get(block=True)
|
|
849
871
|
btn = user_response["button"]
|
|
850
872
|
if btn is None:
|
|
851
873
|
if _state.status.cancel_halt:
|
|
852
874
|
_state.exec_log.log_exit_halt(script, lno, msg="Quit from ASK metacommand")
|
|
853
|
-
|
|
875
|
+
exit_now(2, None)
|
|
854
876
|
else:
|
|
855
877
|
respstr = "Yes" if btn == 1 else "No"
|
|
856
878
|
else:
|
|
857
879
|
if os.name == "posix":
|
|
858
|
-
resp =
|
|
880
|
+
resp = get_yn(message)
|
|
859
881
|
else:
|
|
860
|
-
resp =
|
|
882
|
+
resp = get_yn_win(message)
|
|
861
883
|
if resp == chr(27):
|
|
862
884
|
_state.exec_log.log_exit_halt(script, lno, msg="Quit from ASK metacommand")
|
|
863
|
-
|
|
885
|
+
exit_now(2, None)
|
|
864
886
|
else:
|
|
865
887
|
respstr = "Yes" if resp == "y" else "No"
|
|
866
888
|
subvarset = _state.subvars if subvar[0] != "~" else _state.commandliststack[-1].localvars
|
|
@@ -891,39 +913,39 @@ def x_pause(**kwargs: Any) -> None:
|
|
|
891
913
|
use_gui = False
|
|
892
914
|
if _state.gui_manager_thread:
|
|
893
915
|
return_queue = _queue.Queue()
|
|
894
|
-
_state.gui_manager_queue.put(
|
|
916
|
+
_state.gui_manager_queue.put(GuiSpec(QUERY_CONSOLE, {}, return_queue))
|
|
895
917
|
user_response = return_queue.get(block=True)
|
|
896
918
|
use_gui = user_response["console_running"]
|
|
897
919
|
if use_gui or _state.conf.gui_level > 0:
|
|
898
|
-
|
|
920
|
+
enable_gui()
|
|
899
921
|
return_queue = _queue.Queue()
|
|
900
922
|
gui_args = {
|
|
901
|
-
"title": f"Script {
|
|
923
|
+
"title": f"Script {current_script_line()[0]}",
|
|
902
924
|
"message": msg,
|
|
903
925
|
"countdown": maxtime_secs,
|
|
904
926
|
}
|
|
905
|
-
_state.gui_manager_queue.put(
|
|
927
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_PAUSE, gui_args, return_queue))
|
|
906
928
|
user_response = return_queue.get(block=True)
|
|
907
929
|
quit = user_response["quit"]
|
|
908
930
|
return_queue.task_done()
|
|
909
931
|
else:
|
|
910
932
|
timed_out = False
|
|
911
933
|
if os.name == "posix":
|
|
912
|
-
rv =
|
|
934
|
+
rv = pause(msg, action=action, countdown=maxtime_secs, timeunit=timeunit)
|
|
913
935
|
else:
|
|
914
|
-
rv =
|
|
936
|
+
rv = pause_win(msg, action=action, countdown=maxtime_secs, timeunit=timeunit)
|
|
915
937
|
quit = rv == 1
|
|
916
938
|
timed_out = rv == 2
|
|
917
939
|
if (quit or (timed_out and action == "halt")) and _state.status.cancel_halt:
|
|
918
|
-
_state.exec_log.log_exit_halt(*
|
|
919
|
-
|
|
940
|
+
_state.exec_log.log_exit_halt(*current_script_line(), msg=quitmsg)
|
|
941
|
+
exit_now(2, None)
|
|
920
942
|
return None
|
|
921
943
|
|
|
922
944
|
|
|
923
945
|
def x_halt_msg(**kwargs: Any) -> None:
|
|
924
946
|
errmsg = kwargs["errmsg"]
|
|
925
947
|
tee = kwargs["tee"]
|
|
926
|
-
tee =
|
|
948
|
+
tee = bool(tee)
|
|
927
949
|
outf = kwargs["filename"]
|
|
928
950
|
errlevel = kwargs["errorlevel"]
|
|
929
951
|
if errlevel:
|
|
@@ -932,8 +954,8 @@ def x_halt_msg(**kwargs: Any) -> None:
|
|
|
932
954
|
errlevel = 3
|
|
933
955
|
conf = _state.conf
|
|
934
956
|
if outf:
|
|
935
|
-
|
|
936
|
-
of =
|
|
957
|
+
check_dir(outf)
|
|
958
|
+
of = EncodedFile(outf, conf.output_encoding).open("a")
|
|
937
959
|
of.write(f"{errmsg}\n")
|
|
938
960
|
of.close()
|
|
939
961
|
schema = kwargs.get("schema")
|
|
@@ -945,7 +967,7 @@ def x_halt_msg(**kwargs: Any) -> None:
|
|
|
945
967
|
headers, rows = db.select_data(sql)
|
|
946
968
|
else:
|
|
947
969
|
headers, rows = None, None
|
|
948
|
-
|
|
970
|
+
enable_gui()
|
|
949
971
|
return_queue = _queue.Queue()
|
|
950
972
|
gui_args = {
|
|
951
973
|
"title": "HALT",
|
|
@@ -956,19 +978,19 @@ def x_halt_msg(**kwargs: Any) -> None:
|
|
|
956
978
|
"rowset": rows,
|
|
957
979
|
"help_url": None,
|
|
958
980
|
}
|
|
959
|
-
_state.gui_manager_queue.put(
|
|
981
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_HALT, gui_args, return_queue))
|
|
960
982
|
return_queue.get(block=True)
|
|
961
|
-
_state.exec_log.log_exit_halt(*
|
|
962
|
-
|
|
983
|
+
_state.exec_log.log_exit_halt(*current_script_line(), msg=errmsg)
|
|
984
|
+
exit_now(errlevel, None)
|
|
963
985
|
|
|
964
986
|
|
|
965
987
|
def x_msg(**kwargs: Any) -> None:
|
|
966
988
|
message = kwargs["message"]
|
|
967
|
-
|
|
968
|
-
|
|
989
|
+
current_script_line()
|
|
990
|
+
enable_gui()
|
|
969
991
|
return_queue = _queue.Queue()
|
|
970
992
|
gui_args = {"title": "Message", "message": message}
|
|
971
|
-
_state.gui_manager_queue.put(
|
|
993
|
+
_state.gui_manager_queue.put(GuiSpec(GUI_MSG, gui_args, return_queue))
|
|
972
994
|
return_queue.get(block=True)
|
|
973
995
|
return None
|
|
974
996
|
|