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.
Files changed (90) hide show
  1. execsql/cli.py +322 -108
  2. execsql/config.py +134 -114
  3. execsql/db/access.py +89 -65
  4. execsql/db/base.py +97 -68
  5. execsql/db/dsn.py +45 -29
  6. execsql/db/duckdb.py +4 -5
  7. execsql/db/factory.py +27 -27
  8. execsql/db/firebird.py +30 -18
  9. execsql/db/mysql.py +38 -14
  10. execsql/db/oracle.py +58 -33
  11. execsql/db/postgres.py +68 -28
  12. execsql/db/sqlite.py +36 -27
  13. execsql/db/sqlserver.py +45 -30
  14. execsql/exceptions.py +68 -64
  15. execsql/exporters/__init__.py +1 -1
  16. execsql/exporters/base.py +42 -17
  17. execsql/exporters/delimited.py +60 -59
  18. execsql/exporters/duckdb.py +8 -12
  19. execsql/exporters/feather.py +32 -24
  20. execsql/exporters/html.py +33 -30
  21. execsql/exporters/json.py +18 -17
  22. execsql/exporters/latex.py +11 -13
  23. execsql/exporters/ods.py +50 -46
  24. execsql/exporters/parquet.py +32 -0
  25. execsql/exporters/pretty.py +16 -15
  26. execsql/exporters/raw.py +9 -11
  27. execsql/exporters/sqlite.py +38 -38
  28. execsql/exporters/templates.py +15 -72
  29. execsql/exporters/values.py +13 -12
  30. execsql/exporters/xls.py +26 -26
  31. execsql/exporters/xml.py +12 -12
  32. execsql/exporters/zip.py +0 -3
  33. execsql/gui/__init__.py +2 -2
  34. execsql/gui/console.py +0 -1
  35. execsql/gui/desktop.py +6 -7
  36. execsql/gui/tui.py +8 -14
  37. execsql/importers/base.py +6 -9
  38. execsql/importers/csv.py +10 -17
  39. execsql/importers/feather.py +16 -22
  40. execsql/importers/ods.py +3 -4
  41. execsql/importers/xls.py +5 -6
  42. execsql/metacommands/__init__.py +8 -8
  43. execsql/metacommands/conditions.py +41 -33
  44. execsql/metacommands/connect.py +113 -99
  45. execsql/metacommands/control.py +38 -26
  46. execsql/metacommands/data.py +35 -33
  47. execsql/metacommands/debug.py +13 -9
  48. execsql/metacommands/io.py +288 -229
  49. execsql/metacommands/prompt.py +179 -157
  50. execsql/metacommands/script_ext.py +11 -9
  51. execsql/metacommands/system.py +44 -25
  52. execsql/models.py +9 -16
  53. execsql/parser.py +10 -10
  54. execsql/script.py +183 -157
  55. execsql/state.py +170 -208
  56. execsql/types.py +46 -81
  57. execsql/utils/auth.py +114 -14
  58. execsql/utils/crypto.py +31 -4
  59. execsql/utils/datetime.py +7 -7
  60. execsql/utils/errors.py +34 -29
  61. execsql/utils/fileio.py +90 -55
  62. execsql/utils/gui.py +22 -23
  63. execsql/utils/mail.py +15 -17
  64. execsql/utils/numeric.py +2 -3
  65. execsql/utils/regex.py +9 -12
  66. execsql/utils/strings.py +10 -12
  67. execsql/utils/timer.py +0 -2
  68. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/execsql.conf +1 -1
  69. execsql2-2.1.2.dist-info/METADATA +300 -0
  70. execsql2-2.1.2.dist-info/RECORD +96 -0
  71. execsql2-2.0.1.dist-info/METADATA +0 -406
  72. execsql2-2.0.1.dist-info/RECORD +0 -95
  73. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/READ_ME.rst +0 -0
  74. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/config_settings.sqlite +0 -0
  75. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
  76. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/make_config_db.sql +0 -0
  77. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/md_compare.sql +0 -0
  78. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/md_glossary.sql +0 -0
  79. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/md_upsert.sql +0 -0
  80. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/pg_compare.sql +0 -0
  81. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/pg_glossary.sql +0 -0
  82. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/pg_upsert.sql +0 -0
  83. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/script_template.sql +0 -0
  84. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/ss_compare.sql +0 -0
  85. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/ss_glossary.sql +0 -0
  86. {execsql2-2.0.1.data → execsql2-2.1.2.data}/data/execsql2_extras/ss_upsert.sql +0 -0
  87. {execsql2-2.0.1.dist-info → execsql2-2.1.2.dist-info}/WHEEL +0 -0
  88. {execsql2-2.0.1.dist-info → execsql2-2.1.2.dist-info}/entry_points.txt +0 -0
  89. {execsql2-2.0.1.dist-info → execsql2-2.1.2.dist-info}/licenses/LICENSE.txt +0 -0
  90. {execsql2-2.0.1.dist-info → execsql2-2.1.2.dist-info}/licenses/NOTICE +0 -0
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+ from execsql.exceptions import ErrInfo
2
3
 
3
4
  """
4
5
  Input/output metacommand handlers for execsql.
@@ -17,10 +18,60 @@ metacommands:
17
18
 
18
19
  import os
19
20
  import sys
21
+ from pathlib import Path
20
22
  from shutil import copyfileobj
21
23
  from typing import Any
22
24
 
23
25
  import execsql.state as _state
26
+ from execsql.exporters.base import ExportRecord
27
+ from execsql.exporters.delimited import CsvFile, write_delimited_file
28
+ from execsql.exporters.duckdb import write_query_to_duckdb
29
+ from execsql.exporters.feather import write_query_to_feather, write_query_to_hdf5
30
+ from execsql.exporters.parquet import write_query_to_parquet
31
+ from execsql.exporters.html import write_query_to_cgi_html, write_query_to_html
32
+ from execsql.exporters.json import write_query_to_json, write_query_to_json_ts
33
+ from execsql.exporters.latex import write_query_to_latex
34
+ from execsql.exporters.ods import OdsFile, write_queries_to_ods, write_query_to_ods
35
+ from execsql.exporters.pretty import prettyprint_query, prettyprint_rowset
36
+ from execsql.exporters.raw import write_query_b64, write_query_raw
37
+ from execsql.exporters.sqlite import write_query_to_sqlite
38
+ from execsql.exporters.templates import report_query
39
+ from execsql.exporters.values import write_query_to_values
40
+ from execsql.exporters.xls import XlsFile, XlsxFile
41
+ from execsql.exporters.xml import write_query_to_xml
42
+ from execsql.importers.base import import_data_table
43
+ from execsql.importers.csv import importfile, importtable
44
+ from execsql.importers.feather import import_feather, import_parquet
45
+ from execsql.importers.ods import importods, ods_data
46
+ from execsql.importers.xls import importxls, xls_data
47
+ from execsql.models import DataTable
48
+ from execsql.script import current_script_line, read_sqlfile, substitute_vars
49
+ from execsql.types import dbt_firebird
50
+ from execsql.utils.errors import exception_desc
51
+ from execsql.utils.fileio import check_dir, filewriter_close, filewriter_open_as_new, filewriter_write
52
+ from execsql.utils.gui import ConsoleUIError
53
+ from execsql.utils.strings import clean_words, fold_words, unquoted
54
+
55
+
56
+ def _apply_output_dir(path: str) -> str:
57
+ """Prepend the configured --output-dir to *path* if it is a relative path.
58
+
59
+ If ``conf.export_output_dir`` is set and *path* is not absolute (and not
60
+ ``stdout``), the base directory is joined to *path* so that all EXPORT
61
+ output lands in the same directory without requiring scripts to hard-code
62
+ absolute paths.
63
+ """
64
+ output_dir = getattr(_state.conf, "export_output_dir", None)
65
+ if not output_dir:
66
+ return path
67
+ if path.lower() == "stdout":
68
+ return path
69
+ if Path(path).is_absolute():
70
+ return path
71
+ # Windows drive-letter paths are also absolute
72
+ if len(path) > 1 and path[1] == ":":
73
+ return path
74
+ return str(Path(output_dir) / path)
24
75
 
25
76
 
26
77
  def x_export(**kwargs: Any) -> None:
@@ -28,40 +79,42 @@ def x_export(**kwargs: Any) -> None:
28
79
  table = kwargs["table"]
29
80
  queryname = _state.dbs.current().schema_qualified_table_name(schema, table)
30
81
  select_stmt = f"select * from {queryname};"
31
- outfile = kwargs["filename"]
82
+ outfile = _apply_output_dir(kwargs["filename"])
32
83
  description = kwargs["description"]
33
84
  tee = kwargs["tee"]
34
- tee = False if not tee else True
85
+ tee = bool(tee)
35
86
  append = kwargs["append"]
36
- append = True if append else False
87
+ append = bool(append)
37
88
  filefmt = kwargs["format"].lower()
38
- zipfilename = kwargs["zipfilename"]
89
+ zipfilename = _apply_output_dir(kwargs["zipfilename"]) if kwargs["zipfilename"] else None
39
90
  if zipfilename is not None:
40
91
  if outfile.lower() == "stdout":
41
- raise _state.ErrInfo("error", other_msg="Cannot write stdout to a zipfile.")
92
+ raise ErrInfo("error", other_msg="Cannot write stdout to a zipfile.")
42
93
  elif len(outfile) > 1 and outfile[1] == ":":
43
- raise _state.ErrInfo("error", other_msg="Cannot use a drive letter for a file path within a zipfile.")
94
+ raise ErrInfo("error", other_msg="Cannot use a drive letter for a file path within a zipfile.")
44
95
  if filefmt == "duckdb":
45
- raise _state.ErrInfo("error", other_msg="Cannot export to the DuckDB format within a zipfile.")
96
+ raise ErrInfo("error", other_msg="Cannot export to the DuckDB format within a zipfile.")
46
97
  if filefmt == "sqlite":
47
- raise _state.ErrInfo("error", other_msg="Cannot export to the SQLite format within a zipfile.")
98
+ raise ErrInfo("error", other_msg="Cannot export to the SQLite format within a zipfile.")
48
99
  if filefmt == "latex":
49
- raise _state.ErrInfo("error", other_msg="Cannot export to the LaTeX format within a zipfile.")
100
+ raise ErrInfo("error", other_msg="Cannot export to the LaTeX format within a zipfile.")
50
101
  if filefmt == "feather":
51
- raise _state.ErrInfo("error", other_msg="Cannot export to the feather format within a zipfile.")
102
+ raise ErrInfo("error", other_msg="Cannot export to the feather format within a zipfile.")
103
+ if filefmt == "parquet":
104
+ raise ErrInfo("error", other_msg="Cannot export to the parquet format within a zipfile.")
52
105
  if filefmt == "hdf5":
53
- raise _state.ErrInfo("error", other_msg="Cannot export to the HDF5 format within a zipfile.")
106
+ raise ErrInfo("error", other_msg="Cannot export to the HDF5 format within a zipfile.")
54
107
  if filefmt == "ods":
55
- raise _state.ErrInfo("error", other_msg="Cannot export to an ODS workbook within a zipfile.")
56
- notype = True if kwargs.get("notype") else False
108
+ raise ErrInfo("error", other_msg="Cannot export to an ODS workbook within a zipfile.")
109
+ notype = bool(kwargs.get("notype"))
57
110
  if zipfilename is not None:
58
- _state.check_dir(zipfilename)
111
+ check_dir(zipfilename)
59
112
  else:
60
- _state.check_dir(outfile)
113
+ check_dir(outfile)
61
114
  if tee and outfile.lower() != "stdout":
62
- _state.prettyprint_query(select_stmt, _state.dbs.current(), "stdout", False, desc=description)
115
+ prettyprint_query(select_stmt, _state.dbs.current(), "stdout", False, desc=description)
63
116
  if filefmt in ("txt", "text"):
64
- _state.prettyprint_query(
117
+ prettyprint_query(
65
118
  select_stmt,
66
119
  _state.dbs.current(),
67
120
  outfile,
@@ -70,7 +123,7 @@ def x_export(**kwargs: Any) -> None:
70
123
  zipfile=zipfilename,
71
124
  )
72
125
  elif filefmt in ("txt-and", "text-and"):
73
- _state.prettyprint_query(
126
+ prettyprint_query(
74
127
  select_stmt,
75
128
  _state.dbs.current(),
76
129
  outfile,
@@ -80,7 +133,7 @@ def x_export(**kwargs: Any) -> None:
80
133
  zipfile=zipfilename,
81
134
  )
82
135
  elif filefmt == "ods":
83
- _state.write_query_to_ods(
136
+ write_query_to_ods(
84
137
  select_stmt,
85
138
  _state.dbs.current(),
86
139
  outfile,
@@ -89,11 +142,11 @@ def x_export(**kwargs: Any) -> None:
89
142
  desc=description,
90
143
  )
91
144
  elif filefmt == "duckdb":
92
- _state.write_query_to_duckdb(select_stmt, _state.dbs.current(), outfile, append, tablename=queryname)
145
+ write_query_to_duckdb(select_stmt, _state.dbs.current(), outfile, append, tablename=queryname)
93
146
  elif filefmt == "sqlite":
94
- _state.write_query_to_sqlite(select_stmt, _state.dbs.current(), outfile, append, tablename=queryname)
147
+ write_query_to_sqlite(select_stmt, _state.dbs.current(), outfile, append, tablename=queryname)
95
148
  elif filefmt == "xml":
96
- _state.write_query_to_xml(
149
+ write_query_to_xml(
97
150
  select_stmt,
98
151
  table,
99
152
  _state.dbs.current(),
@@ -103,7 +156,7 @@ def x_export(**kwargs: Any) -> None:
103
156
  zipfile=zipfilename,
104
157
  )
105
158
  elif filefmt == "json":
106
- _state.write_query_to_json(
159
+ write_query_to_json(
107
160
  select_stmt,
108
161
  _state.dbs.current(),
109
162
  outfile,
@@ -112,7 +165,7 @@ def x_export(**kwargs: Any) -> None:
112
165
  zipfile=zipfilename,
113
166
  )
114
167
  elif filefmt in ("json_ts", "json_tableschema"):
115
- _state.write_query_to_json_ts(
168
+ write_query_to_json_ts(
116
169
  select_stmt,
117
170
  _state.dbs.current(),
118
171
  outfile,
@@ -122,7 +175,7 @@ def x_export(**kwargs: Any) -> None:
122
175
  zipfile=zipfilename,
123
176
  )
124
177
  elif filefmt == "values":
125
- _state.write_query_to_values(
178
+ write_query_to_values(
126
179
  select_stmt,
127
180
  _state.dbs.current(),
128
181
  outfile,
@@ -131,7 +184,7 @@ def x_export(**kwargs: Any) -> None:
131
184
  zipfile=zipfilename,
132
185
  )
133
186
  elif filefmt == "html":
134
- _state.write_query_to_html(
187
+ write_query_to_html(
135
188
  select_stmt,
136
189
  _state.dbs.current(),
137
190
  outfile,
@@ -140,7 +193,7 @@ def x_export(**kwargs: Any) -> None:
140
193
  zipfile=zipfilename,
141
194
  )
142
195
  elif filefmt == "cgi-html":
143
- _state.write_query_to_cgi_html(
196
+ write_query_to_cgi_html(
144
197
  select_stmt,
145
198
  _state.dbs.current(),
146
199
  outfile,
@@ -149,7 +202,7 @@ def x_export(**kwargs: Any) -> None:
149
202
  zipfile=zipfilename,
150
203
  )
151
204
  elif filefmt == "latex":
152
- _state.write_query_to_latex(
205
+ write_query_to_latex(
153
206
  select_stmt,
154
207
  _state.dbs.current(),
155
208
  outfile,
@@ -158,23 +211,25 @@ def x_export(**kwargs: Any) -> None:
158
211
  zipfile=zipfilename,
159
212
  )
160
213
  elif filefmt == "hdf5":
161
- _state.write_query_to_hdf5(table, select_stmt, _state.dbs.current(), outfile, append, desc=description)
214
+ write_query_to_hdf5(table, select_stmt, _state.dbs.current(), outfile, append, desc=description)
162
215
  else:
163
216
  try:
164
217
  hdrs, rows = _state.dbs.current().select_rowsource(select_stmt)
165
- except _state.ErrInfo:
218
+ except ErrInfo:
166
219
  raise
167
220
  except Exception:
168
- raise _state.ErrInfo("db", select_stmt, exception_msg=_state.exception_desc())
221
+ raise ErrInfo("db", select_stmt, exception_msg=exception_desc())
169
222
  if filefmt == "raw":
170
- _state.write_query_raw(outfile, rows, _state.dbs.current().encoding, append, zipfile=zipfilename)
223
+ write_query_raw(outfile, rows, _state.dbs.current().encoding, append, zipfile=zipfilename)
171
224
  elif filefmt == "b64":
172
- _state.write_query_b64(outfile, rows, append)
225
+ write_query_b64(outfile, rows, append)
173
226
  elif filefmt == "feather":
174
- _state.write_query_to_feather(outfile, hdrs, rows)
227
+ write_query_to_feather(outfile, hdrs, rows)
228
+ elif filefmt == "parquet":
229
+ write_query_to_parquet(outfile, hdrs, rows)
175
230
  else:
176
- _state.write_delimited_file(outfile, filefmt, hdrs, rows, _state.conf.output_encoding, append, zipfilename)
177
- _state.export_metadata.add(_state.ExportRecord(queryname, outfile, zipfilename, description))
231
+ write_delimited_file(outfile, filefmt, hdrs, rows, _state.conf.output_encoding, append, zipfilename)
232
+ _state.export_metadata.add(ExportRecord(queryname, outfile, zipfilename, description))
178
233
  return None
179
234
 
180
235
 
@@ -183,30 +238,32 @@ def x_export_query(**kwargs: Any) -> None:
183
238
  outfile = kwargs["filename"]
184
239
  description = kwargs["description"]
185
240
  tee = kwargs["tee"]
186
- tee = False if not tee else True
241
+ tee = bool(tee)
187
242
  append = kwargs["append"]
188
- append = True if append else False
243
+ append = bool(append)
189
244
  filefmt = kwargs["format"].lower()
190
245
  zipfilename = kwargs["zipfilename"]
191
246
  if zipfilename is not None:
192
247
  if outfile == "stdout":
193
- raise _state.ErrInfo("error", other_msg="Cannot write stdout to a zipfile.")
248
+ raise ErrInfo("error", other_msg="Cannot write stdout to a zipfile.")
194
249
  elif len(outfile) > 1 and outfile[1] == ":":
195
- raise _state.ErrInfo("error", other_msg="Cannot use a drive letter for a file path within a zipfile.")
250
+ raise ErrInfo("error", other_msg="Cannot use a drive letter for a file path within a zipfile.")
196
251
  if filefmt == "latex":
197
- raise _state.ErrInfo("error", other_msg="Cannot export to the LaTeX format within a zipfile.")
252
+ raise ErrInfo("error", other_msg="Cannot export to the LaTeX format within a zipfile.")
198
253
  if filefmt == "feather":
199
- raise _state.ErrInfo("error", other_msg="Cannot export to the feather format within a zipfile.")
254
+ raise ErrInfo("error", other_msg="Cannot export to the feather format within a zipfile.")
255
+ if filefmt == "parquet":
256
+ raise ErrInfo("error", other_msg="Cannot export to the parquet format within a zipfile.")
200
257
  if filefmt == "hdf5":
201
- raise _state.ErrInfo("error", other_msg="Cannot export to the HDF5 format within a zipfile.")
258
+ raise ErrInfo("error", other_msg="Cannot export to the HDF5 format within a zipfile.")
202
259
  if filefmt == "ods":
203
- raise _state.ErrInfo("error", other_msg="Cannot export to an ODS workbook within a zipfile.")
204
- notype = True if kwargs.get("notype") else False
205
- _state.check_dir(outfile)
260
+ raise ErrInfo("error", other_msg="Cannot export to an ODS workbook within a zipfile.")
261
+ notype = bool(kwargs.get("notype"))
262
+ check_dir(outfile)
206
263
  if tee and outfile.lower() != "stdout":
207
- _state.prettyprint_query(select_stmt, _state.dbs.current(), "stdout", False, desc=description)
264
+ prettyprint_query(select_stmt, _state.dbs.current(), "stdout", False, desc=description)
208
265
  if filefmt in ("txt", "text"):
209
- _state.prettyprint_query(
266
+ prettyprint_query(
210
267
  select_stmt,
211
268
  _state.dbs.current(),
212
269
  outfile,
@@ -215,7 +272,7 @@ def x_export_query(**kwargs: Any) -> None:
215
272
  zipfile=zipfilename,
216
273
  )
217
274
  elif filefmt in ("txt-and", "text-and"):
218
- _state.prettyprint_query(
275
+ prettyprint_query(
219
276
  select_stmt,
220
277
  _state.dbs.current(),
221
278
  outfile,
@@ -225,8 +282,8 @@ def x_export_query(**kwargs: Any) -> None:
225
282
  zipfile=zipfilename,
226
283
  )
227
284
  elif filefmt == "ods":
228
- script_name, lno = _state.current_script_line()
229
- _state.write_query_to_ods(
285
+ script_name, lno = current_script_line()
286
+ write_query_to_ods(
230
287
  select_stmt,
231
288
  _state.dbs.current(),
232
289
  outfile,
@@ -235,7 +292,7 @@ def x_export_query(**kwargs: Any) -> None:
235
292
  desc=description,
236
293
  )
237
294
  elif filefmt == "json":
238
- _state.write_query_to_json(
295
+ write_query_to_json(
239
296
  select_stmt,
240
297
  _state.dbs.current(),
241
298
  outfile,
@@ -244,7 +301,7 @@ def x_export_query(**kwargs: Any) -> None:
244
301
  zipfile=zipfilename,
245
302
  )
246
303
  elif filefmt in ("json_ts", "json_tableschema"):
247
- _state.write_query_to_json_ts(
304
+ write_query_to_json_ts(
248
305
  select_stmt,
249
306
  _state.dbs.current(),
250
307
  outfile,
@@ -254,7 +311,7 @@ def x_export_query(**kwargs: Any) -> None:
254
311
  zipfile=zipfilename,
255
312
  )
256
313
  elif filefmt == "values":
257
- _state.write_query_to_values(
314
+ write_query_to_values(
258
315
  select_stmt,
259
316
  _state.dbs.current(),
260
317
  outfile,
@@ -263,7 +320,7 @@ def x_export_query(**kwargs: Any) -> None:
263
320
  zipfile=zipfilename,
264
321
  )
265
322
  elif filefmt == "html":
266
- _state.write_query_to_html(
323
+ write_query_to_html(
267
324
  select_stmt,
268
325
  _state.dbs.current(),
269
326
  outfile,
@@ -272,7 +329,7 @@ def x_export_query(**kwargs: Any) -> None:
272
329
  zipfile=zipfilename,
273
330
  )
274
331
  elif filefmt == "cgi-html":
275
- _state.write_query_to_cgi_html(
332
+ write_query_to_cgi_html(
276
333
  select_stmt,
277
334
  _state.dbs.current(),
278
335
  outfile,
@@ -281,7 +338,7 @@ def x_export_query(**kwargs: Any) -> None:
281
338
  zipfile=zipfilename,
282
339
  )
283
340
  elif filefmt == "latex":
284
- _state.write_query_to_latex(
341
+ write_query_to_latex(
285
342
  select_stmt,
286
343
  _state.dbs.current(),
287
344
  outfile,
@@ -292,18 +349,20 @@ def x_export_query(**kwargs: Any) -> None:
292
349
  else:
293
350
  try:
294
351
  hdrs, rows = _state.dbs.current().select_rowsource(select_stmt)
295
- except _state.ErrInfo:
352
+ except ErrInfo:
296
353
  raise
297
354
  except Exception:
298
- raise _state.ErrInfo("db", select_stmt, exception_msg=_state.exception_desc())
355
+ raise ErrInfo("db", select_stmt, exception_msg=exception_desc())
299
356
  if filefmt == "raw":
300
- _state.write_query_raw(outfile, rows, _state.dbs.current().encoding, append, zipfile=zipfilename)
357
+ write_query_raw(outfile, rows, _state.dbs.current().encoding, append, zipfile=zipfilename)
301
358
  elif filefmt == "b64":
302
- _state.write_query_b64(outfile, rows, append, zipfile=zipfilename)
359
+ write_query_b64(outfile, rows, append, zipfile=zipfilename)
303
360
  elif filefmt == "feather":
304
- _state.write_query_to_feather(outfile, hdrs, rows)
361
+ write_query_to_feather(outfile, hdrs, rows)
362
+ elif filefmt == "parquet":
363
+ write_query_to_parquet(outfile, hdrs, rows)
305
364
  else:
306
- _state.write_delimited_file(
365
+ write_delimited_file(
307
366
  outfile,
308
367
  filefmt,
309
368
  hdrs,
@@ -312,7 +371,7 @@ def x_export_query(**kwargs: Any) -> None:
312
371
  append,
313
372
  zipfile=zipfilename,
314
373
  )
315
- _state.export_metadata.add(_state.ExportRecord(select_stmt, outfile, zipfilename, description))
374
+ _state.export_metadata.add(ExportRecord(select_stmt, outfile, zipfilename, description))
316
375
  return None
317
376
 
318
377
 
@@ -321,15 +380,15 @@ def x_export_query_with_template(**kwargs: Any) -> None:
321
380
  outfile = kwargs["filename"]
322
381
  template_file = kwargs["template"]
323
382
  tee = kwargs["tee"]
324
- tee = False if not tee else True
383
+ tee = bool(tee)
325
384
  append = kwargs["append"]
326
- append = True if append else False
385
+ append = bool(append)
327
386
  zipfilename = kwargs["zipfilename"]
328
- _state.check_dir(outfile)
387
+ check_dir(outfile)
329
388
  if tee and outfile.lower() != "stdout":
330
- _state.prettyprint_query(select_stmt, _state.dbs.current(), "stdout", False)
331
- _state.report_query(select_stmt, _state.dbs.current(), outfile, template_file, append, zipfile=zipfilename)
332
- _state.export_metadata.add(_state.ExportRecord(select_stmt, outfile, zipfilename))
389
+ prettyprint_query(select_stmt, _state.dbs.current(), "stdout", False)
390
+ report_query(select_stmt, _state.dbs.current(), outfile, template_file, append, zipfile=zipfilename)
391
+ _state.export_metadata.add(ExportRecord(select_stmt, outfile, zipfilename))
333
392
  return None
334
393
 
335
394
 
@@ -341,15 +400,15 @@ def x_export_with_template(**kwargs: Any) -> None:
341
400
  outfile = kwargs["filename"]
342
401
  template_file = kwargs["template"]
343
402
  tee = kwargs["tee"]
344
- tee = False if not tee else True
403
+ tee = bool(tee)
345
404
  append = kwargs["append"]
346
- append = True if append else False
405
+ append = bool(append)
347
406
  zipfilename = kwargs["zipfilename"]
348
- _state.check_dir(outfile)
407
+ check_dir(outfile)
349
408
  if tee and outfile.lower() != "stdout":
350
- _state.prettyprint_query(select_stmt, _state.dbs.current(), "stdout", False)
351
- _state.report_query(select_stmt, _state.dbs.current(), outfile, template_file, append, zipfile=zipfilename)
352
- _state.export_metadata.add(_state.ExportRecord(queryname, outfile, zipfilename))
409
+ prettyprint_query(select_stmt, _state.dbs.current(), "stdout", False)
410
+ report_query(select_stmt, _state.dbs.current(), outfile, template_file, append, zipfile=zipfilename)
411
+ _state.export_metadata.add(ExportRecord(queryname, outfile, zipfilename))
353
412
  return None
354
413
 
355
414
 
@@ -358,11 +417,11 @@ def x_export_ods_multiple(**kwargs: Any) -> None:
358
417
  outfile = kwargs["filename"]
359
418
  description = kwargs["description"]
360
419
  tee = kwargs["tee"]
361
- tee = False if not tee else True
420
+ tee = bool(tee)
362
421
  append = kwargs["append"]
363
- append = False if append is None else True
364
- _state.check_dir(outfile)
365
- _state.write_queries_to_ods(table_list, _state.dbs.current(), outfile, append, tee, desc=description)
422
+ append = append is not None
423
+ check_dir(outfile)
424
+ write_queries_to_ods(table_list, _state.dbs.current(), outfile, append, tee, desc=description)
366
425
 
367
426
 
368
427
  def x_export_metadata(**kwargs: Any) -> None:
@@ -376,11 +435,11 @@ def x_export_metadata(**kwargs: Any) -> None:
376
435
  else:
377
436
  hdrs, rows = _state.export_metadata.get()
378
437
  if outfile.lower() != "stdout":
379
- _state.check_dir(outfile)
438
+ check_dir(outfile)
380
439
  if filefmt in ("txt", "text"):
381
- _state.prettyprint_rowset(hdrs, rows, outfile, append, and_val="", zipfile=zipfilename)
440
+ prettyprint_rowset(hdrs, rows, outfile, append, and_val="", zipfile=zipfilename)
382
441
  else:
383
- _state.write_delimited_file(outfile, filefmt, hdrs, rows, _state.conf.output_encoding, append, zipfilename)
442
+ write_delimited_file(outfile, filefmt, hdrs, rows, _state.conf.output_encoding, append, zipfilename)
384
443
 
385
444
 
386
445
  def x_export_metadata_table(**kwargs: Any) -> None:
@@ -396,7 +455,7 @@ def x_export_metadata_table(**kwargs: Any) -> None:
396
455
  hdrs, rows = _state.export_metadata.get_all()
397
456
  else:
398
457
  hdrs, rows = _state.export_metadata.get()
399
- _state.import_data_table(_state.dbs.current(), schemaname, tablename, is_new, hdrs, rows)
458
+ import_data_table(_state.dbs.current(), schemaname, tablename, is_new, hdrs, rows)
400
459
 
401
460
 
402
461
  def x_import(**kwargs: Any) -> None:
@@ -409,9 +468,9 @@ def x_import(**kwargs: Any) -> None:
409
468
  tablename = kwargs["table"]
410
469
  filename = kwargs["filename"]
411
470
  if len(filename) > 1 and filename[0] == "~" and filename[1] == os.sep:
412
- filename = os.path.join(os.path.expanduser(r"~"), filename[2:])
413
- if not os.path.exists(filename):
414
- raise _state.ErrInfo(
471
+ filename = str(Path.home() / filename[2:])
472
+ if not Path(filename).exists():
473
+ raise ErrInfo(
415
474
  type="cmd",
416
475
  command_text=kwargs["metacommandline"],
417
476
  other_msg=f"Input file {filename} does not exist",
@@ -436,7 +495,7 @@ def x_import(**kwargs: Any) -> None:
436
495
  sz, dt = file_size_date(filename)
437
496
  _state.exec_log.log_status_info(f"IMPORTing {filename} ({sz}, {dt})")
438
497
  try:
439
- _state.importtable(
498
+ importtable(
440
499
  _state.dbs.current(),
441
500
  schemaname,
442
501
  tablename,
@@ -448,12 +507,12 @@ def x_import(**kwargs: Any) -> None:
448
507
  encoding=enc,
449
508
  junk_header_lines=junk_hdrs,
450
509
  )
451
- except _state.ErrInfo:
510
+ except ErrInfo:
452
511
  raise
453
512
  except Exception:
454
- raise _state.ErrInfo(
513
+ raise ErrInfo(
455
514
  "exception",
456
- exception_msg=_state.exception_desc(),
515
+ exception_msg=exception_desc(),
457
516
  other_msg=f"Can't import data from tabular text file {filename}",
458
517
  )
459
518
  return None
@@ -464,8 +523,8 @@ def x_import_file(**kwargs: Any) -> None:
464
523
  tablename = kwargs["table"]
465
524
  columnname = kwargs["columnname"]
466
525
  filename = kwargs["filename"]
467
- if not os.path.exists(filename):
468
- raise _state.ErrInfo(
526
+ if not Path(filename).exists():
527
+ raise ErrInfo(
469
528
  type="cmd",
470
529
  command_text=kwargs["metacommandline"],
471
530
  other_msg=f"Input file {filename} does not exist",
@@ -475,13 +534,13 @@ def x_import_file(**kwargs: Any) -> None:
475
534
  sz, dt = file_size_date(filename)
476
535
  _state.exec_log.log_status_info(f"IMPORTing_FILE {filename} ({sz}, {dt})")
477
536
  try:
478
- _state.importfile(_state.dbs.current(), schemaname, tablename, columnname, filename)
479
- except _state.ErrInfo:
537
+ importfile(_state.dbs.current(), schemaname, tablename, columnname, filename)
538
+ except ErrInfo:
480
539
  raise
481
540
  except Exception:
482
- raise _state.ErrInfo(
541
+ raise ErrInfo(
483
542
  "exception",
484
- exception_msg=_state.exception_desc(),
543
+ exception_msg=exception_desc(),
485
544
  other_msg=f"Can't import file {filename}",
486
545
  )
487
546
  return None
@@ -502,20 +561,20 @@ def x_import_ods(**kwargs: Any) -> None:
502
561
  hdr_rows = 0
503
562
  else:
504
563
  hdr_rows = int(hdr_rows)
505
- if not os.path.exists(filename):
506
- raise _state.ErrInfo(
564
+ if not Path(filename).exists():
565
+ raise ErrInfo(
507
566
  type="cmd",
508
567
  command_text=kwargs["metacommandline"],
509
568
  other_msg="Input file does not exist",
510
569
  )
511
570
  try:
512
- _state.importods(_state.dbs.current(), schemaname, tablename, is_new, filename, sheetname, hdr_rows)
513
- except _state.ErrInfo:
571
+ importods(_state.dbs.current(), schemaname, tablename, is_new, filename, sheetname, hdr_rows)
572
+ except ErrInfo:
514
573
  raise
515
574
  except Exception:
516
- raise _state.ErrInfo(
575
+ raise ErrInfo(
517
576
  "exception",
518
- exception_msg=_state.exception_desc(),
577
+ exception_msg=exception_desc(),
519
578
  other_msg=f"Can't import data from ODS file {filename}",
520
579
  )
521
580
  return None
@@ -537,35 +596,35 @@ def x_import_ods_pattern(**kwargs: Any) -> None:
537
596
  hdr_rows = 0
538
597
  else:
539
598
  hdr_rows = int(hdr_rows)
540
- if not os.path.exists(filename):
541
- raise _state.ErrInfo(
599
+ if not Path(filename).exists():
600
+ raise ErrInfo(
542
601
  type="cmd",
543
602
  command_text=kwargs["metacommandline"],
544
603
  other_msg="Input file does not exist",
545
604
  )
546
- wbk = _state.OdsFile()
605
+ wbk = OdsFile()
547
606
  try:
548
607
  wbk.open(filename)
549
608
  except Exception:
550
- raise _state.ErrInfo(type="cmd", other_msg=f"{filename} is not a valid OpenDocument spreadsheet.")
609
+ raise ErrInfo(type="cmd", other_msg=f"{filename} is not a valid OpenDocument spreadsheet.")
551
610
  sheets = wbk.sheetnames()
552
611
  impsheets = [s for s in sheets if rx.search(s)]
553
612
  tables = list(impsheets)
554
613
  if _state.conf.clean_col_hdrs:
555
- tables = _state.clean_words(tables)
614
+ tables = clean_words(tables)
556
615
  if _state.conf.fold_col_hdrs != "no":
557
- tables = _state.fold_words(tables, _state.conf.fold_col_hdrs)
616
+ tables = fold_words(tables, _state.conf.fold_col_hdrs)
558
617
  for ix in range(len(impsheets)):
559
618
  sheetname = impsheets[ix]
560
619
  tablename = tables[ix]
561
620
  try:
562
- _state.importods(_state.dbs.current(), schemaname, tablename, is_new, filename, sheetname, hdr_rows)
563
- except _state.ErrInfo:
621
+ importods(_state.dbs.current(), schemaname, tablename, is_new, filename, sheetname, hdr_rows)
622
+ except ErrInfo:
564
623
  raise
565
624
  except Exception:
566
- raise _state.ErrInfo(
625
+ raise ErrInfo(
567
626
  "exception",
568
- exception_msg=_state.exception_desc(),
627
+ exception_msg=exception_desc(),
569
628
  other_msg=f"Can't import data from ODS file {filename}",
570
629
  )
571
630
  _state.subvars.add_substitution("$SHEETS_IMPORTED", ",".join(impsheets))
@@ -593,20 +652,20 @@ def x_import_xls(**kwargs: Any) -> None:
593
652
  junk_hdrs = 0
594
653
  else:
595
654
  junk_hdrs = int(junk_hdrs)
596
- if not os.path.exists(filename):
597
- raise _state.ErrInfo(
655
+ if not Path(filename).exists():
656
+ raise ErrInfo(
598
657
  type="cmd",
599
658
  command_text=kwargs["metacommandline"],
600
659
  other_msg="Input file does not exist",
601
660
  )
602
661
  try:
603
- _state.importxls(_state.dbs.current(), schemaname, tablename, is_new, filename, sheetname, junk_hdrs, encoding)
604
- except _state.ErrInfo:
662
+ importxls(_state.dbs.current(), schemaname, tablename, is_new, filename, sheetname, junk_hdrs, encoding)
663
+ except ErrInfo:
605
664
  raise
606
665
  except Exception:
607
- raise _state.ErrInfo(
666
+ raise ErrInfo(
608
667
  "exception",
609
- exception_msg=_state.exception_desc(),
668
+ exception_msg=exception_desc(),
610
669
  other_msg=f"Can't import data from Excel file {filename}",
611
670
  )
612
671
  return None
@@ -629,37 +688,37 @@ def x_import_xls_pattern(**kwargs: Any) -> None:
629
688
  hdr_rows = 0
630
689
  else:
631
690
  hdr_rows = int(hdr_rows)
632
- if not os.path.exists(filename):
633
- raise _state.ErrInfo(
691
+ if not Path(filename).exists():
692
+ raise ErrInfo(
634
693
  type="cmd",
635
694
  command_text=kwargs["metacommandline"],
636
695
  other_msg="Input file does not exist",
637
696
  )
638
697
  if len(filename) < 4:
639
- raise _state.ErrInfo(type="cmd", other_msg=f"{filename} is not a recognizable Excel spreadsheet name.")
698
+ raise ErrInfo(type="cmd", other_msg=f"{filename} is not a recognizable Excel spreadsheet name.")
640
699
  ext3 = filename[-3:].lower()
641
700
  if ext3 == "xls":
642
- wbk = _state.XlsFile()
701
+ wbk = XlsFile()
643
702
  elif ext3 == "lsx":
644
- wbk = _state.XlsxFile()
703
+ wbk = XlsxFile()
645
704
  else:
646
- raise _state.ErrInfo(type="cmd", other_msg=f"{filename} is not a recognizable Excel spreadsheet name.")
705
+ raise ErrInfo(type="cmd", other_msg=f"{filename} is not a recognizable Excel spreadsheet name.")
647
706
  try:
648
707
  wbk.open(filename, encoding, read_only=True)
649
708
  except Exception:
650
- raise _state.ErrInfo(type="cmd", other_msg=f"{filename} is not a valid Excel spreadsheet.")
709
+ raise ErrInfo(type="cmd", other_msg=f"{filename} is not a valid Excel spreadsheet.")
651
710
  sheets = wbk.sheetnames()
652
711
  impsheets = [s for s in sheets if rx.search(s)]
653
712
  tables = list(impsheets)
654
713
  if _state.conf.clean_col_hdrs:
655
- tables = _state.clean_words(tables)
714
+ tables = clean_words(tables)
656
715
  if _state.conf.fold_col_hdrs != "no":
657
- tables = _state.fold_words(tables, _state.conf.fold_col_hdrs)
716
+ tables = fold_words(tables, _state.conf.fold_col_hdrs)
658
717
  for ix in range(len(impsheets)):
659
718
  sheetname = impsheets[ix]
660
719
  tablename = tables[ix]
661
720
  try:
662
- _state.importxls(
721
+ importxls(
663
722
  _state.dbs.current(),
664
723
  schemaname,
665
724
  tablename,
@@ -669,12 +728,12 @@ def x_import_xls_pattern(**kwargs: Any) -> None:
669
728
  hdr_rows,
670
729
  encoding,
671
730
  )
672
- except _state.ErrInfo:
731
+ except ErrInfo:
673
732
  raise
674
733
  except Exception:
675
- raise _state.ErrInfo(
734
+ raise ErrInfo(
676
735
  "exception",
677
- exception_msg=_state.exception_desc(),
736
+ exception_msg=exception_desc(),
678
737
  other_msg=f"Can't import data from ODS file {filename}",
679
738
  )
680
739
  _state.subvars.add_substitution("$SHEETS_IMPORTED", ",".join(impsheets))
@@ -696,9 +755,9 @@ def x_import_parquet(**kwargs: Any) -> None:
696
755
  tablename = kwargs["table"]
697
756
  filename = kwargs["filename"]
698
757
  if len(filename) > 1 and filename[0] == "~" and filename[1] == os.sep:
699
- filename = os.path.join(os.path.expanduser(r"~"), filename[2:])
700
- if not os.path.exists(filename):
701
- raise _state.ErrInfo(
758
+ filename = str(Path.home() / filename[2:])
759
+ if not Path(filename).exists():
760
+ raise ErrInfo(
702
761
  type="cmd",
703
762
  command_text=kwargs["metacommandline"],
704
763
  other_msg=f"Input file {filename} does not exist",
@@ -708,13 +767,13 @@ def x_import_parquet(**kwargs: Any) -> None:
708
767
  sz, dt = file_size_date(filename)
709
768
  _state.exec_log.log_status_info(f"IMPORTing from Parquet file {filename} ({sz}, {dt})")
710
769
  try:
711
- _state.import_parquet(_state.dbs.current(), schemaname, tablename, filename, is_new)
712
- except _state.ErrInfo:
770
+ import_parquet(_state.dbs.current(), schemaname, tablename, filename, is_new)
771
+ except ErrInfo:
713
772
  raise
714
773
  except Exception:
715
- raise _state.ErrInfo(
774
+ raise ErrInfo(
716
775
  "exception",
717
- exception_msg=_state.exception_desc(),
776
+ exception_msg=exception_desc(),
718
777
  other_msg=f"Can't import data from Parquet data file {filename}",
719
778
  )
720
779
  return None
@@ -730,9 +789,9 @@ def x_import_feather(**kwargs: Any) -> None:
730
789
  tablename = kwargs["table"]
731
790
  filename = kwargs["filename"]
732
791
  if len(filename) > 1 and filename[0] == "~" and filename[1] == os.sep:
733
- filename = os.path.join(os.path.expanduser(r"~"), filename[2:])
734
- if not os.path.exists(filename):
735
- raise _state.ErrInfo(
792
+ filename = str(Path.home() / filename[2:])
793
+ if not Path(filename).exists():
794
+ raise ErrInfo(
736
795
  type="cmd",
737
796
  command_text=kwargs["metacommandline"],
738
797
  other_msg=f"Input file {filename} does not exist",
@@ -742,13 +801,13 @@ def x_import_feather(**kwargs: Any) -> None:
742
801
  sz, dt = file_size_date(filename)
743
802
  _state.exec_log.log_status_info(f"IMPORTing from Feather file {filename} ({sz}, {dt})")
744
803
  try:
745
- _state.import_feather(_state.dbs.current(), schemaname, tablename, filename, is_new)
746
- except _state.ErrInfo:
804
+ import_feather(_state.dbs.current(), schemaname, tablename, filename, is_new)
805
+ except ErrInfo:
747
806
  raise
748
807
  except Exception:
749
- raise _state.ErrInfo(
808
+ raise ErrInfo(
750
809
  "exception",
751
- exception_msg=_state.exception_desc(),
810
+ exception_msg=exception_desc(),
752
811
  other_msg=f"Can't import data from Feather data file {filename}",
753
812
  )
754
813
  return None
@@ -767,25 +826,25 @@ def x_export_row_buffer(**kwargs: Any) -> None:
767
826
  def x_write(**kwargs: Any) -> None:
768
827
  msg = f"{kwargs['text']}\n"
769
828
  tee = kwargs["tee"]
770
- tee = False if not tee else True
829
+ tee = bool(tee)
771
830
  outf = kwargs["filename"]
772
831
  if _state.conf.write_prefix is not None:
773
- msg = _state.substitute_vars(_state.conf.write_prefix) + " " + msg
832
+ msg = substitute_vars(_state.conf.write_prefix) + " " + msg
774
833
  if _state.conf.write_suffix is not None:
775
- msg = msg[:-1] + " " + _state.substitute_vars(_state.conf.write_suffix) + "\n"
834
+ msg = msg[:-1] + " " + substitute_vars(_state.conf.write_suffix) + "\n"
776
835
  if outf:
777
- _state.check_dir(outf)
778
- _state.filewriter_write(outf, msg)
836
+ check_dir(outf)
837
+ filewriter_write(outf, msg)
779
838
  if (not outf) or tee:
780
839
  try:
781
840
  _state.output.write(msg)
782
841
  except TypeError:
783
- raise _state.ErrInfo(
842
+ raise ErrInfo(
784
843
  type="other",
785
844
  command_text=kwargs["metacommandline"],
786
845
  other_msg="TypeError in 'write' metacommand.",
787
846
  )
788
- except _state.ConsoleUIError as e:
847
+ except ConsoleUIError as e:
789
848
  _state.output.reset()
790
849
  _state.exec_log.log_status_info(f"Console UI write failed (message {{{e.value}}}); output reset to stdout.")
791
850
  _state.output.write(msg.encode(_state.conf.output_encoding))
@@ -796,8 +855,8 @@ def x_write(**kwargs: Any) -> None:
796
855
 
797
856
  def x_write_create_table(**kwargs: Any) -> None:
798
857
  filename = kwargs["filename"]
799
- if not os.path.exists(filename):
800
- raise _state.ErrInfo(
858
+ if not Path(filename).exists():
859
+ raise ErrInfo(
801
860
  type="cmd",
802
861
  command_text=kwargs["metacommandline"],
803
862
  other_msg="Input file does not exist",
@@ -815,8 +874,8 @@ def x_write_create_table(**kwargs: Any) -> None:
815
874
  junk_hdrs = 0
816
875
  else:
817
876
  junk_hdrs = int(junk_hdrs)
818
- enc = _state.conf.import_encoding if not encoding else encoding
819
- inf = _state.CsvFile(filename, enc, junk_header_lines=junk_hdrs)
877
+ enc = encoding if encoding else _state.conf.import_encoding
878
+ inf = CsvFile(filename, enc, junk_header_lines=junk_hdrs)
820
879
  if quotechar and delimchar:
821
880
  inf.lineformat(delimchar, quotechar, None)
822
881
  inf.evaluate_column_types()
@@ -829,10 +888,10 @@ def x_write_create_table(**kwargs: Any) -> None:
829
888
  if outfile is None or outfile == "stdout":
830
889
  _state.output.write(txt)
831
890
  else:
832
- _state.filewriter_write(outfile, txt)
891
+ filewriter_write(outfile, txt)
833
892
 
834
893
  if outfile:
835
- _state.check_dir(outfile)
894
+ check_dir(outfile)
836
895
  if comment:
837
896
  write(f"-- {comment}\n")
838
897
  write(f"{sql}\n")
@@ -850,20 +909,20 @@ def x_write_create_table_ods(**kwargs: Any) -> None:
850
909
  hdr_rows = int(hdr_rows)
851
910
  comment = kwargs["comment"]
852
911
  outfile = kwargs["outfile"]
853
- if not os.path.exists(filename):
854
- raise _state.ErrInfo(
912
+ if not Path(filename).exists():
913
+ raise ErrInfo(
855
914
  type="cmd",
856
915
  command_text=kwargs["metacommandline"],
857
916
  other_msg="Input file does not exist",
858
917
  )
859
- hdrs, data = _state.ods_data(filename, sheetname, hdr_rows)
860
- tablespec = _state.DataTable(hdrs, data)
918
+ hdrs, data = ods_data(filename, sheetname, hdr_rows)
919
+ tablespec = DataTable(hdrs, data)
861
920
  sql = tablespec.create_table(_state.dbs.current().type, schemaname, tablename, pretty=True)
862
921
  if outfile:
863
922
  if comment:
864
- _state.filewriter_write(outfile, f"-- {comment}\n")
865
- _state.filewriter_write(outfile, sql)
866
- _state.filewriter_close(outfile)
923
+ filewriter_write(outfile, f"-- {comment}\n")
924
+ filewriter_write(outfile, sql)
925
+ filewriter_close(outfile)
867
926
  else:
868
927
  if comment:
869
928
  _state.output.write(f"-- {comment}\n")
@@ -877,27 +936,27 @@ def x_write_create_table_xls(**kwargs: Any) -> None:
877
936
  sheetname = kwargs["sheet"]
878
937
  junk_hdrs = kwargs["skip"]
879
938
  encoding = kwargs["encoding"]
880
- enc = _state.conf.import_encoding if not encoding else encoding
939
+ enc = encoding if encoding else _state.conf.import_encoding
881
940
  if not junk_hdrs:
882
941
  junk_hdrs = 0
883
942
  else:
884
943
  junk_hdrs = int(junk_hdrs)
885
944
  comment = kwargs["comment"]
886
945
  outfile = kwargs["outfile"]
887
- if not os.path.exists(filename):
888
- raise _state.ErrInfo(
946
+ if not Path(filename).exists():
947
+ raise ErrInfo(
889
948
  type="cmd",
890
949
  command_text=kwargs["metacommandline"],
891
950
  other_msg="Input file does not exist",
892
951
  )
893
- hdrs, data = _state.xls_data(filename, sheetname, junk_hdrs, enc)
894
- tablespec = _state.DataTable(hdrs, data)
952
+ hdrs, data = xls_data(filename, sheetname, junk_hdrs, enc)
953
+ tablespec = DataTable(hdrs, data)
895
954
  sql = tablespec.create_table(_state.dbs.current().type, schemaname, tablename, pretty=True)
896
955
  if outfile:
897
956
  if comment:
898
- _state.filewriter_write(outfile, f"-- {comment}\n")
899
- _state.filewriter_write(outfile, sql)
900
- _state.filewriter_close(outfile)
957
+ filewriter_write(outfile, f"-- {comment}\n")
958
+ filewriter_write(outfile, sql)
959
+ filewriter_close(outfile)
901
960
  else:
902
961
  if comment:
903
962
  _state.output.write(f"-- {comment}\n")
@@ -911,7 +970,7 @@ def x_write_create_table_alias(**kwargs: Any) -> None:
911
970
  comment = kwargs["comment"]
912
971
  outfile = kwargs["filename"]
913
972
  if alias not in _state.dbs.aliases():
914
- raise _state.ErrInfo(
973
+ raise ErrInfo(
915
974
  type="cmd",
916
975
  command_text=kwargs["metacommandline"],
917
976
  other_msg=f"Unrecognized database alias: {alias}.",
@@ -920,27 +979,27 @@ def x_write_create_table_alias(**kwargs: Any) -> None:
920
979
  tbl = db.schema_qualified_table_name(schema, table)
921
980
  try:
922
981
  if not db.table_exists(table, schema):
923
- raise _state.ErrInfo(
982
+ raise ErrInfo(
924
983
  type="cmd",
925
984
  command_text=kwargs["metacommandline"],
926
985
  other_msg=f"Table {tbl} does not exist",
927
986
  )
928
987
  except Exception:
929
- pass
988
+ pass # Best-effort check; some adapters lack information_schema.
930
989
  select_stmt = f"select * from {tbl};"
931
990
  try:
932
991
  hdrs, rows = db.select_rowsource(select_stmt)
933
- except _state.ErrInfo:
992
+ except ErrInfo:
934
993
  raise
935
994
  except Exception:
936
- raise _state.ErrInfo("db", select_stmt, exception_msg=_state.exception_desc())
937
- tablespec = _state.DataTable(hdrs, rows)
995
+ raise ErrInfo("db", select_stmt, exception_msg=exception_desc())
996
+ tablespec = DataTable(hdrs, rows)
938
997
  sql = tablespec.create_table(_state.dbs.current().type, kwargs["schema1"], kwargs["table1"], pretty=True)
939
998
  if outfile:
940
999
  if comment:
941
- _state.filewriter_write(outfile, f"-- {comment}\n")
942
- _state.filewriter_write(outfile, sql)
943
- _state.filewriter_close(outfile)
1000
+ filewriter_write(outfile, f"-- {comment}\n")
1001
+ filewriter_write(outfile, sql)
1002
+ filewriter_close(outfile)
944
1003
  else:
945
1004
  if comment:
946
1005
  _state.output.write(f"-- {comment}\n")
@@ -974,12 +1033,12 @@ def x_writescript(**kwargs: Any) -> None:
974
1033
  if output_dest is None or output_dest == "stdout":
975
1034
  _state.output.write(txt)
976
1035
  else:
977
- _state.filewriter_write(output_dest, txt)
1036
+ filewriter_write(output_dest, txt)
978
1037
 
979
1038
  if output_dest is not None and output_dest != "stdout":
980
- _state.check_dir(output_dest)
1039
+ check_dir(output_dest)
981
1040
  if not append:
982
- _state.filewriter_open_as_new(output_dest)
1041
+ filewriter_open_as_new(output_dest)
983
1042
  script = _state.savedscripts[script_id]
984
1043
  if script.paramnames is not None and len(script.paramnames) > 0:
985
1044
  write(f"BEGIN SCRIPT {script_id} ({', '.join(script.paramnames)})\n")
@@ -994,15 +1053,15 @@ def x_writescript(**kwargs: Any) -> None:
994
1053
  def x_include(**kwargs: Any) -> None:
995
1054
  filename = kwargs["filename"]
996
1055
  if len(filename) > 1 and filename[0] == "~" and filename[1] == os.sep:
997
- filename = os.path.join(os.path.expanduser(r"~"), filename[2:])
1056
+ filename = str(Path.home() / filename[2:])
998
1057
  exists = kwargs["exists"]
999
1058
  if exists is not None:
1000
- if os.path.isfile(filename):
1001
- _state.read_sqlfile(filename)
1059
+ if Path(filename).is_file():
1060
+ read_sqlfile(filename)
1002
1061
  else:
1003
- if not os.path.isfile(filename):
1004
- raise _state.ErrInfo(type="error", other_msg=f"File {filename} does not exist.")
1005
- _state.read_sqlfile(filename)
1062
+ if not Path(filename).is_file():
1063
+ raise ErrInfo(type="error", other_msg=f"File {filename} does not exist.")
1064
+ read_sqlfile(filename)
1006
1065
  return None
1007
1066
 
1008
1067
 
@@ -1016,13 +1075,13 @@ def x_copy(**kwargs: Any) -> None:
1016
1075
  schema2 = kwargs["schema2"]
1017
1076
  table2 = kwargs["table2"]
1018
1077
  if alias1 not in _state.dbs.aliases():
1019
- raise _state.ErrInfo(
1078
+ raise ErrInfo(
1020
1079
  type="cmd",
1021
1080
  command_text=kwargs["metacommandline"],
1022
1081
  other_msg=f"Unrecognized database alias: {alias1}.",
1023
1082
  )
1024
1083
  if alias2 not in _state.dbs.aliases():
1025
- raise _state.ErrInfo(
1084
+ raise ErrInfo(
1026
1085
  type="cmd",
1027
1086
  command_text=kwargs["metacommandline"],
1028
1087
  other_msg=f"Unrecognized database alias: {alias2}.",
@@ -1033,29 +1092,29 @@ def x_copy(**kwargs: Any) -> None:
1033
1092
  tbl2 = db2.schema_qualified_table_name(schema2, table2)
1034
1093
  try:
1035
1094
  if not db1.table_exists(table1, schema1):
1036
- raise _state.ErrInfo(
1095
+ raise ErrInfo(
1037
1096
  type="cmd",
1038
1097
  command_text=kwargs["metacommandline"],
1039
1098
  other_msg=f"Table {tbl1} does not exist",
1040
1099
  )
1041
1100
  except Exception:
1042
- pass
1101
+ pass # Best-effort check; some adapters lack information_schema.
1043
1102
  if new_tbl2 and new_tbl2 == "new":
1044
1103
  try:
1045
1104
  if db2.table_exists(table2, schema2):
1046
- raise _state.ErrInfo(
1105
+ raise ErrInfo(
1047
1106
  type="cmd",
1048
1107
  command_text=kwargs["metacommandline"],
1049
1108
  other_msg=f"Table {tbl2} already exists",
1050
1109
  )
1051
1110
  except Exception:
1052
- pass
1111
+ pass # Best-effort check; some adapters lack information_schema.
1053
1112
  select_stmt = f"select * from {tbl1};"
1054
1113
 
1055
- def get_ts() -> _state.DataTable:
1114
+ def get_ts() -> DataTable:
1056
1115
  if get_ts.tablespec is None:
1057
1116
  hdrs, rows = db1.select_rowsource(select_stmt)
1058
- get_ts.tablespec = _state.DataTable(hdrs, rows)
1117
+ get_ts.tablespec = DataTable(hdrs, rows)
1059
1118
  return get_ts.tablespec
1060
1119
 
1061
1120
  get_ts.tablespec = None
@@ -1069,21 +1128,21 @@ def x_copy(**kwargs: Any) -> None:
1069
1128
  except Exception:
1070
1129
  _state.exec_log.log_status_info(f"Could not drop existing table ({tbl2}) for COPY metacommand")
1071
1130
  db2.execute(create_tbl)
1072
- if db2.type == _state.dbt_firebird:
1131
+ if db2.type == dbt_firebird:
1073
1132
  db2.execute("COMMIT;")
1074
1133
  try:
1075
1134
  hdrs, rows = db1.select_rowsource(select_stmt)
1076
- except _state.ErrInfo:
1135
+ except ErrInfo:
1077
1136
  raise
1078
1137
  except Exception:
1079
- raise _state.ErrInfo("db", select_stmt, exception_msg=_state.exception_desc())
1138
+ raise ErrInfo("db", select_stmt, exception_msg=exception_desc())
1080
1139
  try:
1081
1140
  db2.populate_table(schema2, table2, rows, hdrs, get_ts)
1082
1141
  db2.commit()
1083
- except _state.ErrInfo:
1142
+ except ErrInfo:
1084
1143
  raise
1085
1144
  except Exception:
1086
- raise _state.ErrInfo("db", select_stmt, exception_msg=_state.exception_desc())
1145
+ raise ErrInfo("db", select_stmt, exception_msg=exception_desc())
1087
1146
 
1088
1147
 
1089
1148
  def x_copy_query(**kwargs: Any) -> None:
@@ -1095,13 +1154,13 @@ def x_copy_query(**kwargs: Any) -> None:
1095
1154
  schema2 = kwargs["schema"]
1096
1155
  table2 = kwargs["table"]
1097
1156
  if alias1 not in _state.dbs.aliases():
1098
- raise _state.ErrInfo(
1157
+ raise ErrInfo(
1099
1158
  type="cmd",
1100
1159
  command_text=kwargs["metacommandline"],
1101
1160
  other_msg=f"Unrecognized database alias: {alias1}.",
1102
1161
  )
1103
1162
  if alias2 not in _state.dbs.aliases():
1104
- raise _state.ErrInfo(
1163
+ raise ErrInfo(
1105
1164
  type="cmd",
1106
1165
  command_text=kwargs["metacommandline"],
1107
1166
  other_msg=f"Unrecognized database alias: {alias2}.",
@@ -1112,18 +1171,18 @@ def x_copy_query(**kwargs: Any) -> None:
1112
1171
  if new_tbl2 and new_tbl2 == "new":
1113
1172
  try:
1114
1173
  if db2.table_exists(table2, schema2):
1115
- raise _state.ErrInfo(
1174
+ raise ErrInfo(
1116
1175
  type="cmd",
1117
1176
  command_text=kwargs["metacommandline"],
1118
1177
  other_msg=f"Table {tbl2} already exists",
1119
1178
  )
1120
1179
  except Exception:
1121
- pass
1180
+ pass # Best-effort check; some adapters lack information_schema.
1122
1181
 
1123
- def get_ts() -> _state.DataTable:
1182
+ def get_ts() -> DataTable:
1124
1183
  if not get_ts.tablespec:
1125
1184
  hdrs, rows = db1.select_rowsource(select_stmt)
1126
- get_ts.tablespec = _state.DataTable(hdrs, rows)
1185
+ get_ts.tablespec = DataTable(hdrs, rows)
1127
1186
  return get_ts.tablespec
1128
1187
 
1129
1188
  get_ts.tablespec = None
@@ -1131,11 +1190,11 @@ def x_copy_query(**kwargs: Any) -> None:
1131
1190
  if new_tbl2:
1132
1191
  try:
1133
1192
  hdrs, rows = db1.select_rowsource(select_stmt)
1134
- except _state.ErrInfo:
1193
+ except ErrInfo:
1135
1194
  raise
1136
1195
  except Exception:
1137
- raise _state.ErrInfo("db", select_stmt, exception_msg=_state.exception_desc())
1138
- get_ts.tablespec = _state.DataTable(hdrs, rows)
1196
+ raise ErrInfo("db", select_stmt, exception_msg=exception_desc())
1197
+ get_ts.tablespec = DataTable(hdrs, rows)
1139
1198
  tbl_desc = get_ts.tablespec
1140
1199
  create_tbl = tbl_desc.create_table(db2.type, schema2, table2)
1141
1200
  if new_tbl2 == "replacement":
@@ -1144,21 +1203,21 @@ def x_copy_query(**kwargs: Any) -> None:
1144
1203
  except Exception:
1145
1204
  _state.exec_log.log_status_info(f"Could not drop existing table ({tbl2}) for COPY metacommand")
1146
1205
  db2.execute(create_tbl)
1147
- if db2.type == _state.dbt_firebird:
1206
+ if db2.type == dbt_firebird:
1148
1207
  db2.execute("COMMIT;")
1149
1208
  try:
1150
1209
  hdrs, rows = db1.select_rowsource(select_stmt)
1151
- except _state.ErrInfo:
1210
+ except ErrInfo:
1152
1211
  raise
1153
1212
  except Exception:
1154
- raise _state.ErrInfo("db", select_stmt, exception_msg=_state.exception_desc())
1213
+ raise ErrInfo("db", select_stmt, exception_msg=exception_desc())
1155
1214
  try:
1156
1215
  db2.populate_table(schema2, table2, rows, hdrs, get_ts)
1157
1216
  db2.commit()
1158
- except _state.ErrInfo:
1217
+ except ErrInfo:
1159
1218
  raise
1160
1219
  except Exception:
1161
- raise _state.ErrInfo("db", select_stmt, exception_msg=_state.exception_desc())
1220
+ raise ErrInfo("db", select_stmt, exception_msg=exception_desc())
1162
1221
 
1163
1222
 
1164
1223
  def x_zip(**kwargs: Any) -> None:
@@ -1172,7 +1231,7 @@ def x_zip(**kwargs: Any) -> None:
1172
1231
  zf = _zipfile.ZipFile(zipfile_name, mode=zmode, compression=_zipfile.ZIP_BZIP2, compresslevel=9)
1173
1232
  fnlist = _glob.glob(files)
1174
1233
  for f in fnlist:
1175
- if os.path.isfile(f):
1234
+ if Path(f).is_file():
1176
1235
  zf.write(f)
1177
1236
  zf.close()
1178
1237
 
@@ -1188,8 +1247,8 @@ def x_rm_file(**kwargs: Any) -> None:
1188
1247
  fn = kwargs["filename"].strip(' "')
1189
1248
  fnlist = _glob.glob(fn)
1190
1249
  for f in fnlist:
1191
- if os.path.isfile(f):
1192
- _state.filewriter_close(f)
1250
+ if Path(f).is_file():
1251
+ filewriter_close(f)
1193
1252
  os.unlink(f)
1194
1253
 
1195
1254
 
@@ -1199,15 +1258,15 @@ def x_make_export_dirs(**kwargs: Any) -> None:
1199
1258
 
1200
1259
 
1201
1260
  def x_cd(**kwargs: Any) -> None:
1202
- new_dir = _state.unquoted(kwargs["dir"])
1203
- if not os.path.isdir(new_dir):
1204
- raise _state.ErrInfo(
1261
+ new_dir = unquoted(kwargs["dir"])
1262
+ if not Path(new_dir).is_dir():
1263
+ raise ErrInfo(
1205
1264
  type="cmd",
1206
1265
  command_text=kwargs["metacommandline"],
1207
1266
  other_msg="Directory does not exist",
1208
1267
  )
1209
1268
  os.chdir(new_dir)
1210
- script, lno = _state.current_script_line()
1269
+ script, lno = current_script_line()
1211
1270
  _state.exec_log.log_status_info(f"Current directory changed to {new_dir} at line {lno} of {script}")
1212
1271
  return None
1213
1272
 
@@ -1223,13 +1282,13 @@ def x_hdf5_text_len(**kwargs: Any) -> None:
1223
1282
  def x_serve(**kwargs: Any) -> None:
1224
1283
  infname = kwargs["filename"]
1225
1284
  fmt = kwargs["format"].lower()
1226
- if not os.path.isfile(infname):
1227
- raise _state.ErrInfo(
1285
+ if not Path(infname).is_file():
1286
+ raise ErrInfo(
1228
1287
  type="cmd",
1229
1288
  command_text=kwargs["metacommandline"],
1230
1289
  other_msg=f"Input file {infname} does not exist",
1231
1290
  )
1232
- fname = os.path.basename(infname)
1291
+ fname = Path(infname).name
1233
1292
  if fmt == "binary":
1234
1293
  contenttype = "application/octet-stream"
1235
1294
  elif fmt == "csv":