execsql2 2.0.0a2__py3-none-any.whl → 2.1.1__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 +173 -215
- 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.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/execsql.conf +1 -1
- execsql2-2.1.1.dist-info/METADATA +295 -0
- execsql2-2.1.1.dist-info/RECORD +96 -0
- execsql2-2.0.0a2.dist-info/METADATA +0 -406
- execsql2-2.0.0a2.dist-info/RECORD +0 -95
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/READ_ME.rst +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/config_settings.sqlite +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/make_config_db.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/md_compare.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/md_glossary.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/md_upsert.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/pg_compare.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/pg_glossary.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/pg_upsert.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/script_template.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/ss_compare.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/ss_glossary.sql +0 -0
- {execsql2-2.0.0a2.data → execsql2-2.1.1.data}/data/execsql2_extras/ss_upsert.sql +0 -0
- {execsql2-2.0.0a2.dist-info → execsql2-2.1.1.dist-info}/WHEEL +0 -0
- {execsql2-2.0.0a2.dist-info → execsql2-2.1.1.dist-info}/entry_points.txt +0 -0
- {execsql2-2.0.0a2.dist-info → execsql2-2.1.1.dist-info}/licenses/LICENSE.txt +0 -0
- {execsql2-2.0.0a2.dist-info → execsql2-2.1.1.dist-info}/licenses/NOTICE +0 -0
|
@@ -13,15 +13,17 @@ Implements metacommands that extend or augment a running script:
|
|
|
13
13
|
from typing import Any
|
|
14
14
|
|
|
15
15
|
import execsql.state as _state
|
|
16
|
+
from execsql.exceptions import ErrInfo
|
|
17
|
+
from execsql.script import MetacommandStmt, ScriptCmd, ScriptExecSpec, SqlStmt, current_script_line
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
def x_extendscript(**kwargs: Any) -> None:
|
|
19
21
|
script1 = kwargs["script1"].lower()
|
|
20
22
|
if script1 not in _state.savedscripts:
|
|
21
|
-
raise
|
|
23
|
+
raise ErrInfo("cmd", other_msg=f"There is no SCRIPT named {script1}.")
|
|
22
24
|
script2 = kwargs["script2"].lower()
|
|
23
25
|
if script2 not in _state.savedscripts:
|
|
24
|
-
raise
|
|
26
|
+
raise ErrInfo("cmd", other_msg=f"There is no SCRIPT named {script2}.")
|
|
25
27
|
s1 = _state.savedscripts[script1]
|
|
26
28
|
s2 = _state.savedscripts[script2]
|
|
27
29
|
for cmd in s1.cmdlist:
|
|
@@ -37,20 +39,20 @@ def x_extendscript(**kwargs: Any) -> None:
|
|
|
37
39
|
def x_extendscript_metacommand(**kwargs: Any) -> None:
|
|
38
40
|
script = kwargs["script"].lower()
|
|
39
41
|
if script not in _state.savedscripts:
|
|
40
|
-
raise
|
|
41
|
-
script_file, script_line_no =
|
|
42
|
+
raise ErrInfo("cmd", other_msg=f"There is no SCRIPT named {script}.")
|
|
43
|
+
script_file, script_line_no = current_script_line()
|
|
42
44
|
_state.savedscripts[script].add(
|
|
43
|
-
|
|
45
|
+
ScriptCmd(script_file, script_line_no, "cmd", MetacommandStmt(kwargs["cmd"])),
|
|
44
46
|
)
|
|
45
47
|
|
|
46
48
|
|
|
47
49
|
def x_extendscript_sql(**kwargs: Any) -> None:
|
|
48
50
|
script = kwargs["script"].lower()
|
|
49
51
|
if script not in _state.savedscripts:
|
|
50
|
-
raise
|
|
51
|
-
script_file, script_line_no =
|
|
52
|
+
raise ErrInfo("cmd", other_msg=f"There is no SCRIPT named {script}.")
|
|
53
|
+
script_file, script_line_no = current_script_line()
|
|
52
54
|
_state.savedscripts[script].add(
|
|
53
|
-
|
|
55
|
+
ScriptCmd(script_file, script_line_no, "sql", SqlStmt(kwargs["sql"])),
|
|
54
56
|
)
|
|
55
57
|
|
|
56
58
|
|
|
@@ -58,4 +60,4 @@ def x_executescript(**kwargs: Any) -> None:
|
|
|
58
60
|
exists = kwargs["exists"]
|
|
59
61
|
script_id = kwargs["script_id"].lower()
|
|
60
62
|
if exists is None or (exists is not None and script_id in _state.savedscripts):
|
|
61
|
-
|
|
63
|
+
ScriptExecSpec(**kwargs).execute()
|
execsql/metacommands/system.py
CHANGED
|
@@ -14,20 +14,39 @@ import subprocess
|
|
|
14
14
|
from typing import Any
|
|
15
15
|
|
|
16
16
|
import execsql.state as _state
|
|
17
|
+
from execsql.exceptions import ErrInfo
|
|
18
|
+
from execsql.exporters.base import WriteSpec
|
|
19
|
+
from execsql.script import ScriptExecSpec, current_script_line
|
|
20
|
+
from execsql.utils.errors import exception_desc
|
|
21
|
+
from execsql.utils.fileio import filewriter_close_all_after_write
|
|
22
|
+
from execsql.utils.gui import (
|
|
23
|
+
gui_console_height,
|
|
24
|
+
gui_console_hide,
|
|
25
|
+
gui_console_off,
|
|
26
|
+
gui_console_on,
|
|
27
|
+
gui_console_progress,
|
|
28
|
+
gui_console_save,
|
|
29
|
+
gui_console_show,
|
|
30
|
+
gui_console_status,
|
|
31
|
+
gui_console_wait_user,
|
|
32
|
+
gui_console_width,
|
|
33
|
+
)
|
|
34
|
+
from execsql.utils.mail import MailSpec, Mailer
|
|
35
|
+
from execsql.utils.strings import is_doublequoted
|
|
17
36
|
|
|
18
37
|
|
|
19
38
|
def x_system_cmd(**kwargs: Any) -> None:
|
|
20
39
|
syscmd = kwargs["command"]
|
|
21
40
|
cont = kwargs["continue"]
|
|
22
|
-
script, lno =
|
|
41
|
+
script, lno = current_script_line()
|
|
23
42
|
_state.exec_log.log_user_msg(f"System command on line {lno} of script {script}: {syscmd}")
|
|
24
|
-
|
|
43
|
+
filewriter_close_all_after_write()
|
|
25
44
|
if os.name != "posix":
|
|
26
45
|
syscmd = syscmd.replace("\\", "\\\\")
|
|
27
46
|
cmdlist = shlex.split(syscmd)
|
|
28
47
|
else:
|
|
29
48
|
cmdlist = shlex.split(syscmd, posix=True)
|
|
30
|
-
cmdargs = ['"' + cmd + '"' if "&" in cmd and not
|
|
49
|
+
cmdargs = ['"' + cmd + '"' if "&" in cmd and not is_doublequoted(cmd) else cmd for cmd in cmdlist]
|
|
31
50
|
if cont is None:
|
|
32
51
|
returncode = subprocess.call(cmdargs)
|
|
33
52
|
_state.subvars.add_substitution("$SYSTEM_CMD_EXIT_STATUS", str(returncode))
|
|
@@ -43,7 +62,7 @@ def x_email(**kwargs: Any) -> None:
|
|
|
43
62
|
msg = kwargs["msg"]
|
|
44
63
|
msg_file = kwargs["msg_file"]
|
|
45
64
|
att_file = kwargs["att_file"]
|
|
46
|
-
m =
|
|
65
|
+
m = Mailer()
|
|
47
66
|
m.sendmail(from_addr, to_addr, subject, msg, msg_file, att_file)
|
|
48
67
|
|
|
49
68
|
|
|
@@ -73,9 +92,9 @@ def x_log_datavars(**kwargs: Any) -> None:
|
|
|
73
92
|
def x_console(**kwargs: Any) -> None:
|
|
74
93
|
onoff = kwargs["onoff"].lower()
|
|
75
94
|
if onoff == "on":
|
|
76
|
-
|
|
95
|
+
gui_console_on()
|
|
77
96
|
else:
|
|
78
|
-
|
|
97
|
+
gui_console_off()
|
|
79
98
|
|
|
80
99
|
|
|
81
100
|
def x_consoleprogress(**kwargs: Any) -> None:
|
|
@@ -83,12 +102,12 @@ def x_consoleprogress(**kwargs: Any) -> None:
|
|
|
83
102
|
total = kwargs["total"]
|
|
84
103
|
if total:
|
|
85
104
|
num = 100 * num / float(total)
|
|
86
|
-
|
|
105
|
+
gui_console_progress(num)
|
|
87
106
|
|
|
88
107
|
|
|
89
108
|
def x_consolewait(**kwargs: Any) -> None:
|
|
90
109
|
message = kwargs["message"]
|
|
91
|
-
|
|
110
|
+
gui_console_wait_user(message)
|
|
92
111
|
|
|
93
112
|
|
|
94
113
|
def x_consolewait_onerror(**kwargs: Any) -> None:
|
|
@@ -104,39 +123,39 @@ def x_consolewait_whendone(**kwargs: Any) -> None:
|
|
|
104
123
|
def x_console_hideshow(**kwargs: Any) -> None:
|
|
105
124
|
hideshow = kwargs["hideshow"].lower()
|
|
106
125
|
if hideshow == "hide":
|
|
107
|
-
|
|
126
|
+
gui_console_hide()
|
|
108
127
|
else:
|
|
109
|
-
|
|
128
|
+
gui_console_show()
|
|
110
129
|
|
|
111
130
|
|
|
112
131
|
def x_consolewidth(**kwargs: Any) -> None:
|
|
113
132
|
width = kwargs["width"]
|
|
114
133
|
_state.conf.gui_console_width = int(width)
|
|
115
|
-
|
|
134
|
+
gui_console_width(width)
|
|
116
135
|
|
|
117
136
|
|
|
118
137
|
def x_consoleheight(**kwargs: Any) -> None:
|
|
119
138
|
height = kwargs["height"]
|
|
120
139
|
_state.conf.gui_console_height = int(height)
|
|
121
|
-
|
|
140
|
+
gui_console_height(height)
|
|
122
141
|
|
|
123
142
|
|
|
124
143
|
def x_consolestatus(**kwargs: Any) -> None:
|
|
125
144
|
message = kwargs["message"]
|
|
126
|
-
|
|
145
|
+
gui_console_status(message)
|
|
127
146
|
|
|
128
147
|
|
|
129
148
|
def x_consolesave(**kwargs: Any) -> None:
|
|
130
149
|
fn = kwargs["filename"]
|
|
131
150
|
ap = kwargs["append"]
|
|
132
151
|
append = ap is not None
|
|
133
|
-
|
|
152
|
+
gui_console_save(fn, append)
|
|
134
153
|
|
|
135
154
|
|
|
136
155
|
def x_cancel_halt(**kwargs: Any) -> None:
|
|
137
156
|
flag = kwargs["onoff"].lower()
|
|
138
157
|
if flag not in ("on", "off", "yes", "no", "true", "false"):
|
|
139
|
-
raise
|
|
158
|
+
raise ErrInfo(
|
|
140
159
|
type="cmd",
|
|
141
160
|
command_text=kwargs["metacommandline"],
|
|
142
161
|
other_msg=f"Unrecognized flag for handling GUI cancellations: {flag}",
|
|
@@ -152,9 +171,9 @@ def x_cancel_halt_write_clear(**kwargs: Any) -> None:
|
|
|
152
171
|
def x_cancel_halt_write(**kwargs: Any) -> None:
|
|
153
172
|
msg = f"{kwargs['text']}\n"
|
|
154
173
|
tee = kwargs["tee"]
|
|
155
|
-
tee =
|
|
174
|
+
tee = bool(tee)
|
|
156
175
|
outf = kwargs["filename"]
|
|
157
|
-
_state.cancel_halt_writespec =
|
|
176
|
+
_state.cancel_halt_writespec = WriteSpec(message=msg, dest=outf, tee=tee)
|
|
158
177
|
|
|
159
178
|
|
|
160
179
|
def x_cancel_halt_email_clear(**kwargs: Any) -> None:
|
|
@@ -168,11 +187,11 @@ def x_cancel_halt_email(**kwargs: Any) -> None:
|
|
|
168
187
|
msg = kwargs["msg"]
|
|
169
188
|
msg_file = kwargs["msg_file"]
|
|
170
189
|
att_file = kwargs["att_file"]
|
|
171
|
-
_state.cancel_halt_mailspec =
|
|
190
|
+
_state.cancel_halt_mailspec = MailSpec(from_addr, to_addr, subject, msg, msg_file, att_file)
|
|
172
191
|
|
|
173
192
|
|
|
174
193
|
def x_cancel_halt_exec(**kwargs: Any) -> None:
|
|
175
|
-
_state.cancel_halt_exec =
|
|
194
|
+
_state.cancel_halt_exec = ScriptExecSpec(**kwargs)
|
|
176
195
|
|
|
177
196
|
|
|
178
197
|
def x_cancel_halt_exec_clear(**kwargs: Any) -> None:
|
|
@@ -186,9 +205,9 @@ def x_error_halt_write_clear(**kwargs: Any) -> None:
|
|
|
186
205
|
def x_error_halt_write(**kwargs: Any) -> None:
|
|
187
206
|
msg = f"{kwargs['text']}\n"
|
|
188
207
|
tee = kwargs["tee"]
|
|
189
|
-
tee =
|
|
208
|
+
tee = bool(tee)
|
|
190
209
|
outf = kwargs["filename"]
|
|
191
|
-
_state.err_halt_writespec =
|
|
210
|
+
_state.err_halt_writespec = WriteSpec(message=msg, dest=outf, tee=tee)
|
|
192
211
|
|
|
193
212
|
|
|
194
213
|
def x_error_halt_email_clear(**kwargs: Any) -> None:
|
|
@@ -202,11 +221,11 @@ def x_error_halt_email(**kwargs: Any) -> None:
|
|
|
202
221
|
msg = kwargs["msg"]
|
|
203
222
|
msg_file = kwargs["msg_file"]
|
|
204
223
|
att_file = kwargs["att_file"]
|
|
205
|
-
_state.err_halt_email =
|
|
224
|
+
_state.err_halt_email = MailSpec(from_addr, to_addr, subject, msg, msg_file, att_file)
|
|
206
225
|
|
|
207
226
|
|
|
208
227
|
def x_error_halt_exec(**kwargs: Any) -> None:
|
|
209
|
-
_state.err_halt_exec =
|
|
228
|
+
_state.err_halt_exec = ScriptExecSpec(**kwargs)
|
|
210
229
|
|
|
211
230
|
|
|
212
231
|
def x_error_halt_exec_clear(**kwargs: Any) -> None:
|
|
@@ -230,8 +249,8 @@ def x_execute(**kwargs: Any) -> None:
|
|
|
230
249
|
try:
|
|
231
250
|
db.exec_cmd(sql)
|
|
232
251
|
db.commit()
|
|
233
|
-
except
|
|
252
|
+
except ErrInfo:
|
|
234
253
|
raise
|
|
235
254
|
except Exception:
|
|
236
|
-
raise
|
|
255
|
+
raise ErrInfo("db", command_text=sql, exception_msg=exception_desc())
|
|
237
256
|
return None
|
execsql/models.py
CHANGED
|
@@ -18,9 +18,8 @@ This module provides:
|
|
|
18
18
|
``"string"``, etc.).
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
import copy
|
|
22
21
|
import re
|
|
23
|
-
from typing import Any
|
|
22
|
+
from typing import Any
|
|
24
23
|
|
|
25
24
|
from execsql.exceptions import ColumnError, DataTableError
|
|
26
25
|
from execsql.types import (
|
|
@@ -60,15 +59,9 @@ class Column:
|
|
|
60
59
|
self.varscale = False
|
|
61
60
|
|
|
62
61
|
def __repr__(self) -> str:
|
|
63
|
-
return
|
|
64
|
-
self.dt.data_type_name
|
|
65
|
-
self.
|
|
66
|
-
self.count,
|
|
67
|
-
self.maxlen,
|
|
68
|
-
self.varlen,
|
|
69
|
-
self.maxprecision,
|
|
70
|
-
self.scale,
|
|
71
|
-
self.varscale,
|
|
62
|
+
return (
|
|
63
|
+
f"Data type {self.dt.data_type_name}; failed={self.failed}; count={self.count}; maxlen={self.maxlen};"
|
|
64
|
+
f" varlen={self.varlen}, precision={self.maxprecision}, scale={self.scale}, varscale={self.varscale}"
|
|
72
65
|
)
|
|
73
66
|
|
|
74
67
|
def check(self, datavalue: Any) -> None:
|
|
@@ -160,7 +153,7 @@ class Column:
|
|
|
160
153
|
if conf.trim_strings:
|
|
161
154
|
column_value = column_value.strip()
|
|
162
155
|
if conf.replace_newlines:
|
|
163
|
-
column_value = re.sub(r"\s\t]*[\r\n]+[\s\t]*", " ", column_value)
|
|
156
|
+
column_value = re.sub(r"[\s\t]*[\r\n]+[\s\t]*", " ", column_value)
|
|
164
157
|
if column_value is None or (
|
|
165
158
|
not conf.empty_strings and isinstance(column_value, str) and len(column_value.strip()) == 0
|
|
166
159
|
):
|
|
@@ -202,7 +195,7 @@ class Column:
|
|
|
202
195
|
self.dt = (
|
|
203
196
|
self.name,
|
|
204
197
|
sel_type.dt.__class__,
|
|
205
|
-
None if not sel_type.dt.lenspec else
|
|
198
|
+
None if not sel_type.dt.lenspec else sel_type.maxlen,
|
|
206
199
|
self.nullrows > 0,
|
|
207
200
|
sel_type.maxprecision,
|
|
208
201
|
sel_type.scale,
|
|
@@ -212,7 +205,7 @@ class Column:
|
|
|
212
205
|
|
|
213
206
|
|
|
214
207
|
class DataTable:
|
|
215
|
-
def __init__(self, column_names:
|
|
208
|
+
def __init__(self, column_names: list[str], rowsource: Any) -> None:
|
|
216
209
|
import execsql.state as _state
|
|
217
210
|
|
|
218
211
|
self.inputrows = 0 # Total number of rows in the row source.
|
|
@@ -263,7 +256,7 @@ class DataTable:
|
|
|
263
256
|
def __repr__(self) -> str:
|
|
264
257
|
return f"DataTable({[col.name for col in self.cols]!r}, rowsource)"
|
|
265
258
|
|
|
266
|
-
def column_declarations(self, database_type: DbType) ->
|
|
259
|
+
def column_declarations(self, database_type: DbType) -> list[str]:
|
|
267
260
|
# Returns a list of column specifications.
|
|
268
261
|
spec = []
|
|
269
262
|
for col in self.cols:
|
|
@@ -273,7 +266,7 @@ class DataTable:
|
|
|
273
266
|
def create_table(
|
|
274
267
|
self,
|
|
275
268
|
database_type: DbType,
|
|
276
|
-
schemaname:
|
|
269
|
+
schemaname: str | None,
|
|
277
270
|
tablename: str,
|
|
278
271
|
pretty: bool = False,
|
|
279
272
|
) -> str:
|
execsql/parser.py
CHANGED
|
@@ -23,7 +23,7 @@ Classes:
|
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
import re
|
|
26
|
-
from typing import Any
|
|
26
|
+
from typing import Any
|
|
27
27
|
|
|
28
28
|
from execsql.exceptions import CondParserError, NumericParserError
|
|
29
29
|
|
|
@@ -42,7 +42,7 @@ class SourceString:
|
|
|
42
42
|
while not self.eoi() and self.str[self.currpos] in [" ", "\t", "\n"]:
|
|
43
43
|
self.currpos += 1
|
|
44
44
|
|
|
45
|
-
def match_str(self, str: str) ->
|
|
45
|
+
def match_str(self, str: str) -> str | None:
|
|
46
46
|
# Tries to match the 'str' argument at the current position in the
|
|
47
47
|
# source string. Matching is case-insensitive. If matching succeeds,
|
|
48
48
|
# the matched string is returned and the internal pointer is incremented.
|
|
@@ -59,7 +59,7 @@ class SourceString:
|
|
|
59
59
|
else:
|
|
60
60
|
return None
|
|
61
61
|
|
|
62
|
-
def match_regex(self, regex: Any) ->
|
|
62
|
+
def match_regex(self, regex: Any) -> dict | None:
|
|
63
63
|
# Tries to match the 'regex' argument at the current position in the
|
|
64
64
|
# source string. If it succeeds, a dictionary of all of the named
|
|
65
65
|
# groups is returned, and the internal pointer is incremented.
|
|
@@ -74,7 +74,7 @@ class SourceString:
|
|
|
74
74
|
else:
|
|
75
75
|
return None
|
|
76
76
|
|
|
77
|
-
def match_metacommand(self, commandlist: Any) ->
|
|
77
|
+
def match_metacommand(self, commandlist: Any) -> tuple | None:
|
|
78
78
|
# Tries to match text at the current position to any metacommand
|
|
79
79
|
# in the specified commandlist.
|
|
80
80
|
# If it succeeds, the return value is a tuple of the MetaCommand object
|
|
@@ -185,21 +185,21 @@ class CondParser(CondTokens):
|
|
|
185
185
|
self.condexpr = condexpr
|
|
186
186
|
self.cond_expr = SourceString(condexpr)
|
|
187
187
|
|
|
188
|
-
def match_not(self) ->
|
|
188
|
+
def match_not(self) -> int | None:
|
|
189
189
|
# Try to match 'NOT' operator. If not found, return None
|
|
190
190
|
m1 = self.cond_expr.match_str("NOT")
|
|
191
191
|
if m1 is not None:
|
|
192
192
|
return self.NOT
|
|
193
193
|
return None
|
|
194
194
|
|
|
195
|
-
def match_andop(self) ->
|
|
195
|
+
def match_andop(self) -> int | None:
|
|
196
196
|
# Try to match 'AND' operator. If not found, return None
|
|
197
197
|
m1 = self.cond_expr.match_str("AND")
|
|
198
198
|
if m1 is not None:
|
|
199
199
|
return self.AND
|
|
200
200
|
return None
|
|
201
201
|
|
|
202
|
-
def match_orop(self) ->
|
|
202
|
+
def match_orop(self) -> int | None:
|
|
203
203
|
# Try to match 'OR' operator. If not found, return None
|
|
204
204
|
m1 = self.cond_expr.match_str("OR")
|
|
205
205
|
if m1 is not None:
|
|
@@ -270,7 +270,7 @@ class NumericParser(NumTokens):
|
|
|
270
270
|
self.rxint = re.compile(r"(?P<int_num>[+-]?[0-9]+)")
|
|
271
271
|
self.rxfloat = re.compile(r"(?P<float_num>[+-]?(?:(?:[0-9]*\.[0-9]+)|(?:[0-9]+\.[0-9]*)))")
|
|
272
272
|
|
|
273
|
-
def match_number(self) ->
|
|
273
|
+
def match_number(self) -> Any | None:
|
|
274
274
|
# Try to match a number in the source string.
|
|
275
275
|
# Return it if matched, return None if unmatched.
|
|
276
276
|
m1 = self.num_expr.match_regex(self.rxfloat)
|
|
@@ -282,7 +282,7 @@ class NumericParser(NumTokens):
|
|
|
282
282
|
return int(m2["int_num"])
|
|
283
283
|
return None
|
|
284
284
|
|
|
285
|
-
def match_mulop(self) ->
|
|
285
|
+
def match_mulop(self) -> int | None:
|
|
286
286
|
# Try to match a multiplication or division operator in the source string.
|
|
287
287
|
# if found, return the matching operator type. If not found, return None.
|
|
288
288
|
m1 = self.num_expr.match_str("*")
|
|
@@ -294,7 +294,7 @@ class NumericParser(NumTokens):
|
|
|
294
294
|
return self.DIV
|
|
295
295
|
return None
|
|
296
296
|
|
|
297
|
-
def match_addop(self) ->
|
|
297
|
+
def match_addop(self) -> int | None:
|
|
298
298
|
# Try to match an addition or subtraction operator in the source string.
|
|
299
299
|
# if found, return the matching operator type. If not found, return None.
|
|
300
300
|
m1 = self.num_expr.match_str("+")
|