Skip to content

Commit a8affb3

Browse files
committed
move show_warnings from main.py to iocommands.py
The globals may not be pretty, but the file location is more correct. The behavior of the CLI overriding the config file is preserved, but that logic is moved to MyCli construction instead of within connect(), which is also a better location for computing configuration. Some tangential tests are included since other regression tests are wholly deleted.
1 parent 9341037 commit a8affb3

File tree

10 files changed

+138
-101
lines changed

10 files changed

+138
-101
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Internal
4848
* Move CLI utilities to a new `cli_utils.py`.
4949
* Move keybinding utilities to a new `key_binding_utils.py`.
5050
* Move interactive utilities to `interactive_utils.py`.
51+
* Move special commands out of `main.py`.
5152
* Modernize orthography of prompt_toolkit filters.
5253
* Pin all GitHub Actions to hashes.
5354

mycli/main.py

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ def __init__(
143143
auto_vertical_output: bool = False,
144144
warn: bool | None = None,
145145
myclirc: str = "~/.myclirc",
146+
show_warnings: bool | None = None,
146147
) -> None:
147148
self.sqlexecute = sqlexecute
148149
self.logfile = logfile
@@ -176,6 +177,10 @@ def __init__(
176177
self.vi_ttimeoutlen = c['keys'].as_float('vi_ttimeoutlen')
177178
special.set_timing_enabled(c["main"].as_bool("timing"))
178179
special.set_show_favorite_query(c["main"].as_bool("show_favorite_query"))
180+
if show_warnings is not None:
181+
special.set_show_warnings_enabled(show_warnings)
182+
else:
183+
special.set_show_warnings_enabled(c['main'].as_bool('show_warnings'))
179184
self.beep_after_seconds = float(c["main"]["beep_after_seconds"] or 0)
180185
self.default_keepalive_ticks = c['connection'].as_int('default_keepalive_ticks')
181186

@@ -221,7 +226,6 @@ def __init__(
221226

222227
# read from cli argument or user config file
223228
self.auto_vertical_output = auto_vertical_output or c["main"].as_bool("auto_vertical_output")
224-
self.show_warnings = c["main"].as_bool("show_warnings")
225229

226230
# Write user config if system config wasn't the last config loaded.
227231
if c.filename not in self.system_config_files and not os.path.exists(myclirc):
@@ -326,22 +330,6 @@ def register_special_commands(self) -> None:
326330
aliases=["\\Tr"],
327331
case_sensitive=True,
328332
)
329-
special.register_special_command(
330-
self.disable_show_warnings,
331-
"nowarnings",
332-
"nowarnings",
333-
"Disable automatic warnings display.",
334-
aliases=["\\w"],
335-
case_sensitive=True,
336-
)
337-
special.register_special_command(
338-
self.enable_show_warnings,
339-
"warnings",
340-
"warnings",
341-
"Enable automatic warnings display.",
342-
aliases=["\\W"],
343-
case_sensitive=True,
344-
)
345333
special.register_special_command(
346334
self.execute_from_file, "source", "source <filename>", "Execute queries from a file.", aliases=["\\."]
347335
)
@@ -361,16 +349,6 @@ def manual_reconnect(self, arg: str = "", **_) -> Generator[SQLResult, None, Non
361349
else:
362350
yield self.change_db(arg).send(None)
363351

364-
def enable_show_warnings(self, **_) -> Generator[SQLResult, None, None]:
365-
self.show_warnings = True
366-
msg = "Show warnings enabled."
367-
yield SQLResult(status=msg)
368-
369-
def disable_show_warnings(self, **_) -> Generator[SQLResult, None, None]:
370-
self.show_warnings = False
371-
msg = "Show warnings disabled."
372-
yield SQLResult(status=msg)
373-
374352
def change_table_format(self, arg: str, **_) -> Generator[SQLResult, None, None]:
375353
try:
376354
self.main_formatter.format_name = arg
@@ -555,7 +533,6 @@ def connect(
555533
use_keyring: bool | None = None,
556534
reset_keyring: bool | None = None,
557535
keepalive_ticks: int | None = None,
558-
show_warnings: bool | None = None,
559536
) -> None:
560537
cnf = {
561538
"database": None,
@@ -585,8 +562,6 @@ def connect(
585562
ssl_config: dict[str, Any] = ssl or {}
586563
user_connection_config = self.config_without_package_defaults.get('connection', {})
587564
self.keepalive_ticks = keepalive_ticks
588-
if show_warnings is not None:
589-
self.show_warnings = show_warnings
590565

591566
int_port = port and int(port)
592567
if not int_port:
@@ -1070,7 +1045,7 @@ def run_query(
10701045
click.echo(line, nl=new_line)
10711046

10721047
# get and display warnings if enabled
1073-
if self.show_warnings and isinstance(result.rows, Cursor) and result.rows.warning_count > 0:
1048+
if special.is_show_warnings_enabled() and isinstance(result.rows, Cursor) and result.rows.warning_count > 0:
10741049
warnings = self.sqlexecute.run("SHOW WARNINGS")
10751050
for warning in warnings:
10761051
output = self.format_sqlresult(
@@ -1537,6 +1512,7 @@ def get_password_from_file(password_file: str | None) -> str | None:
15371512
auto_vertical_output=cli_args.auto_vertical_output,
15381513
warn=cli_args.warn,
15391514
myclirc=cli_args.myclirc,
1515+
show_warnings=cli_args.show_warnings,
15401516
)
15411517

15421518
if cli_args.checkup:
@@ -1898,7 +1874,6 @@ def get_password_from_file(password_file: str | None) -> str | None:
18981874
use_keyring=use_keyring,
18991875
reset_keyring=reset_keyring,
19001876
keepalive_ticks=keepalive_ticks,
1901-
show_warnings=cli_args.show_warnings,
19021877
)
19031878

19041879
if combined_init_cmd:

mycli/main_modes/repl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def _output_results(
411411
result_count += 1
412412
state.mutating = state.mutating or is_mutating(result.status_plain)
413413

414-
if mycli.show_warnings and isinstance(result.rows, Cursor) and result.rows.warning_count > 0:
414+
if special.is_show_warnings_enabled() and isinstance(result.rows, Cursor) and result.rows.warning_count > 0:
415415
warnings = sqlexecute.run('SHOW WARNINGS')
416416
warnings_duration = time.time() - start
417417
saw_warning = False

mycli/packages/special/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
close_tee,
99
copy_query_to_clipboard,
1010
disable_pager,
11+
disable_show_warnings,
1112
editor_command,
13+
enable_show_warnings,
1214
flush_pipe_once_if_written,
1315
forced_horizontal,
1416
get_clip_query,
@@ -19,6 +21,7 @@
1921
is_pager_enabled,
2022
is_redirected,
2123
is_show_favorite_query,
24+
is_show_warnings_enabled,
2225
is_timing_enabled,
2326
open_external_editor,
2427
set_delimiter,
@@ -30,6 +33,7 @@
3033
set_pager_enabled,
3134
set_redirect,
3235
set_show_favorite_query,
36+
set_show_warnings_enabled,
3337
set_timing_enabled,
3438
split_queries,
3539
unset_once_if_written,
@@ -58,7 +62,9 @@
5862
'close_tee',
5963
'copy_query_to_clipboard',
6064
'disable_pager',
65+
'disable_show_warnings',
6166
'editor_command',
67+
'enable_show_warnings',
6268
'execute',
6369
'flush_pipe_once_if_written',
6470
'forced_horizontal',
@@ -71,6 +77,7 @@
7177
'is_llm_command',
7278
'is_pager_enabled',
7379
'is_redirected',
80+
'is_show_warnings_enabled',
7481
'is_timing_enabled',
7582
'list_databases',
7683
'list_tables',
@@ -85,6 +92,7 @@
8592
'set_pager',
8693
'set_pager_enabled',
8794
'set_redirect',
95+
'set_show_warnings_enabled',
8896
'set_timing_enabled',
8997
'set_show_favorite_query',
9098
'is_show_favorite_query',

mycli/packages/special/iocommands.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
delimiter_command = DelimiterCommand()
4747
favoritequeries = FavoriteQueries(ConfigObj())
4848
DESTRUCTIVE_KEYWORDS: list[str] = []
49+
SHOW_WARNINGS_ENABLED: bool = False
4950

5051

5152
def set_favorite_queries(config):
@@ -81,6 +82,45 @@ def set_destructive_keywords(val: list[str]) -> None:
8182
DESTRUCTIVE_KEYWORDS = val
8283

8384

85+
def set_show_warnings_enabled(val: bool) -> None:
86+
global SHOW_WARNINGS_ENABLED
87+
SHOW_WARNINGS_ENABLED = val
88+
89+
90+
def is_show_warnings_enabled() -> bool:
91+
return SHOW_WARNINGS_ENABLED
92+
93+
94+
@special_command(
95+
'warnings',
96+
'warnings',
97+
'Enable automatic warnings display.',
98+
arg_type=ArgType.NO_QUERY,
99+
aliases=['\\W'],
100+
case_sensitive=True,
101+
)
102+
def enable_show_warnings() -> Generator[SQLResult, None, None]:
103+
global SHOW_WARNINGS_ENABLED
104+
SHOW_WARNINGS_ENABLED = True
105+
msg = "Show warnings enabled."
106+
yield SQLResult(status=msg)
107+
108+
109+
@special_command(
110+
'nowarnings',
111+
'nowarnings',
112+
'Disable automatic warnings display.',
113+
arg_type=ArgType.NO_QUERY,
114+
aliases=['\\w'],
115+
case_sensitive=True,
116+
)
117+
def disable_show_warnings() -> Generator[SQLResult, None, None]:
118+
global SHOW_WARNINGS_ENABLED
119+
SHOW_WARNINGS_ENABLED = False
120+
msg = 'Show warnings disabled.'
121+
yield SQLResult(status=msg)
122+
123+
84124
@special_command(
85125
"pager",
86126
"pager [command]",

test/pytests/test_main.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
PORT,
3838
TEMPFILE_PREFIX,
3939
USER,
40+
DummyFormatter,
41+
FakeCursorBase,
4042
ReusableLock,
4143
call_click_entrypoint_direct,
4244
dbtest,
@@ -2324,3 +2326,42 @@ def test_click_entrypoint_callback_covers_mycnf_underscore_fallback(monkeypatch:
23242326

23252327
call_click_entrypoint_direct(main.CliArgs())
23262328
assert any('ssl-ca = /tmp/ca.pem' in line for line in click_lines)
2329+
2330+
2331+
def test_format_sqlresult_uses_redirect_formatter_when_redirected() -> None:
2332+
cli = make_bare_mycli()
2333+
cli.main_formatter = DummyFormatter()
2334+
cli.redirect_formatter = DummyFormatter()
2335+
2336+
result = SQLResult(header=['id'], rows=[(1,)], status='ok')
2337+
assert list(main.MyCli.format_sqlresult(cli, result, is_redirected=True)) == ['plain output']
2338+
2339+
assert cli.main_formatter.calls == []
2340+
assert len(cli.redirect_formatter.calls) == 1
2341+
2342+
2343+
def test_format_sqlresult_materializes_cursor_rows_when_width_is_limited(monkeypatch: pytest.MonkeyPatch) -> None:
2344+
cli = make_bare_mycli()
2345+
cli.main_formatter = DummyFormatter()
2346+
rows = FakeCursorBase(rows=[(1,)], rowcount=1, description=[('id', 3)])
2347+
monkeypatch.setattr(main, 'Cursor', FakeCursorBase)
2348+
2349+
result = SQLResult(header=['id'], rows=cast(Any, rows), status='ok')
2350+
list(main.MyCli.format_sqlresult(cli, result, max_width=100))
2351+
2352+
formatted_rows = cli.main_formatter.calls[-1][0][0]
2353+
assert formatted_rows == [(1,)]
2354+
2355+
2356+
def test_format_sqlresult_appends_postamble() -> None:
2357+
cli = make_bare_mycli()
2358+
result = SQLResult(header=['id'], rows=[(1,)], status='ok', postamble='done')
2359+
2360+
assert list(main.MyCli.format_sqlresult(cli, result))[-1] == 'done'
2361+
2362+
2363+
def test_get_last_query_returns_latest_query() -> None:
2364+
cli = make_bare_mycli()
2365+
cli.query_history = [main.Query('select 1', True, False)]
2366+
2367+
assert main.MyCli.get_last_query(cli) == 'select 1'

test/pytests/test_main_modes_repl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,6 @@ def run(self, text: str) -> list[SQLResult]:
526526
cli.auto_vertical_output = True
527527
cli.prompt_session = FakePromptSession(columns=91)
528528
cli.beep_after_seconds = 0.1
529-
cli.show_warnings = True
530529
state = repl_mode.ReplState()
531530
format_widths: list[int | None] = []
532531

@@ -539,6 +538,7 @@ def format_sqlresult(result: SQLResult, **kwargs: Any) -> Iterator[str]:
539538
monkeypatch.setattr(repl_mode.time, 'time', lambda: next(time_values))
540539
monkeypatch.setattr(repl_mode.special, 'is_expanded_output', lambda: False)
541540
monkeypatch.setattr(repl_mode.special, 'is_redirected', lambda: False)
541+
monkeypatch.setattr(repl_mode.special, 'is_show_warnings_enabled', lambda: True)
542542
monkeypatch.setattr(repl_mode.special, 'is_timing_enabled', lambda: True)
543543
monkeypatch.setattr(repl_mode, 'Cursor', FakeCursorBase)
544544
monkeypatch.setattr(repl_mode, 'is_select', lambda status: False)

0 commit comments

Comments
 (0)