From 0a33388f6c77c855c3c340f3a4f4dd98b323aa3b Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Mon, 5 May 2025 18:51:40 +0100 Subject: [PATCH 01/13] Add --- Lib/sqlite3/__main__.py | 11 +++++++++-- Lib/test/test_sqlite3/test_cli.py | 11 +++++++++-- .../2025-05-05-18-50-00.gh-issue-133447.ajshdb.rst | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-05-05-18-50-00.gh-issue-133447.ajshdb.rst diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 79a6209468dae4..266ee91c6f51fb 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -10,6 +10,7 @@ from argparse import ArgumentParser from code import InteractiveConsole from textwrap import dedent +import _colorize as colorize def execute(c, sql, suppress_errors=True): @@ -104,8 +105,14 @@ def main(*args): Each command will be run using execute() on the cursor. Type ".help" for more information; type ".quit" or {eofkey} to quit. """).strip() - sys.ps1 = "sqlite> " - sys.ps2 = " ... " + + use_color = colorize.can_colorize() + + bold_magenta = colorize.ANSIColors.BOLD_MAGENTA if use_color else "" + reset = colorize.ANSIColors.RESET if use_color else "" + + sys.ps1 = f"{bold_magenta}sqlite> {reset}" + sys.ps2 = f"{bold_magenta} ... {reset}" con = sqlite3.connect(args.filename, isolation_level=None) try: diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index dcd90d11d46819..9ed993a8b22ebc 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -3,8 +3,9 @@ import unittest from sqlite3.__main__ import main as cli -from test.support.os_helper import TESTFN, unlink -from test.support import captured_stdout, captured_stderr, captured_stdin +from test.support.os_helper import TESTFN, unlink, EnvironmentVarGuard +from test.support import (captured_stdout, captured_stderr, captured_stdin, + force_not_colorized_test_class) class CommandLineInterface(unittest.TestCase): @@ -63,6 +64,7 @@ def test_cli_on_disk_db(self): self.assertIn("(0,)", out) +@force_not_colorized_test_class class InteractiveSession(unittest.TestCase): MEMORY_DB_MSG = "Connected to a transient in-memory database" PS1 = "sqlite> " @@ -152,6 +154,11 @@ def test_interact_on_disk_file(self): out, _ = self.run_cli(TESTFN, commands=("SELECT count(t) FROM t;",)) self.assertIn("(0,)\n", out) + def test_color(self): + with unittest.mock.patch("_colorize.can_colorize", return_value=True): + out, err = self.run_cli(commands="\n") + self.assertIn("\x1b[1;35msqlite> \x1b[0m", out) + self.assertIn("\x1b[1;35m ... \x1b[0m\x1b", out) if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2025-05-05-18-50-00.gh-issue-133447.ajshdb.rst b/Misc/NEWS.d/next/Library/2025-05-05-18-50-00.gh-issue-133447.ajshdb.rst new file mode 100644 index 00000000000000..f453690cab2cb3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-05-18-50-00.gh-issue-133447.ajshdb.rst @@ -0,0 +1 @@ +Add basic color to :mod:`sqlite3` CLI interface. From e680c354f45559da73e0367f2bf0fc899447c7de Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Mon, 5 May 2025 18:56:54 +0100 Subject: [PATCH 02/13] Import cleanup --- Lib/test/test_sqlite3/test_cli.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index 9ed993a8b22ebc..6ce89ff734ea57 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -3,9 +3,13 @@ import unittest from sqlite3.__main__ import main as cli -from test.support.os_helper import TESTFN, unlink, EnvironmentVarGuard -from test.support import (captured_stdout, captured_stderr, captured_stdin, - force_not_colorized_test_class) +from test.support.os_helper import TESTFN, unlink +from test.support import ( + captured_stdout, + captured_stderr, + captured_stdin, + force_not_colorized_test_class, +) class CommandLineInterface(unittest.TestCase): From b4561334eb4a9dbcabed1d16bf302635ed2123e9 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Mon, 5 May 2025 19:21:10 +0100 Subject: [PATCH 03/13] Highlight error messages --- Lib/sqlite3/__main__.py | 31 ++++++++++++++++++++----------- Lib/test/test_sqlite3/test_cli.py | 3 +++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 8eafe485d30714..f2b6c8f93ebcb8 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -12,8 +12,16 @@ from textwrap import dedent import _colorize as colorize +BOLD_MAGENTA = colorize.ANSIColors.BOLD_MAGENTA +MAGENTA =colorize.ANSIColors.MAGENTA +RESET = colorize.ANSIColors.RESET -def execute(c, sql, suppress_errors=True): +def color(color, use_color): + if use_color: + return color + return '' + +def execute(c, sql, suppress_errors=True, use_color=False): """Helper that wraps execution of SQL code. This is used both by the REPL and by direct execution from the CLI. @@ -28,9 +36,12 @@ def execute(c, sql, suppress_errors=True): except sqlite3.Error as e: tp = type(e).__name__ try: - print(f"{tp} ({e.sqlite_errorname}): {e}", file=sys.stderr) + print(f"{color(BOLD_MAGENTA, use_color)}{tp} ({e.sqlite_errorname})" + f"{color(RESET, use_color)}: " + f"{color(MAGENTA, use_color)}{e}{color(RESET, use_color)}", file=sys.stderr) except AttributeError: - print(f"{tp}: {e}", file=sys.stderr) + print(f"{color(BOLD_MAGENTA, use_color)}{tp}{color(RESET, use_color)}: " + f"{color(MAGENTA, use_color)}{e}{color(RESET, use_color)}", file=sys.stderr) if not suppress_errors: sys.exit(1) @@ -38,10 +49,11 @@ def execute(c, sql, suppress_errors=True): class SqliteInteractiveConsole(InteractiveConsole): """A simple SQLite REPL.""" - def __init__(self, connection): + def __init__(self, connection, use_color=False): super().__init__() self._con = connection self._cur = connection.cursor() + self._use_color = use_color def runsource(self, source, filename="", symbol="single"): """Override runsource, the core of the InteractiveConsole REPL. @@ -59,7 +71,7 @@ def runsource(self, source, filename="", symbol="single"): case _: if not sqlite3.complete_statement(source): return True - execute(self._cur, source) + execute(self._cur, source, use_color=self._use_color) return False @@ -109,11 +121,8 @@ def main(*args): use_color = colorize.can_colorize() - bold_magenta = colorize.ANSIColors.BOLD_MAGENTA if use_color else "" - reset = colorize.ANSIColors.RESET if use_color else "" - - sys.ps1 = f"{bold_magenta}sqlite> {reset}" - sys.ps2 = f"{bold_magenta} ... {reset}" + sys.ps1 = f"{color(BOLD_MAGENTA, use_color)}sqlite> {color(RESET, use_color)}" + sys.ps2 = f"{color(BOLD_MAGENTA, use_color)} ... {color(RESET, use_color)}" con = sqlite3.connect(args.filename, isolation_level=None) try: @@ -122,7 +131,7 @@ def main(*args): execute(con, args.sql, suppress_errors=False) else: # No SQL provided; start the REPL. - console = SqliteInteractiveConsole(con) + console = SqliteInteractiveConsole(con, use_color) try: import readline # noqa: F401 except ImportError: diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index 82eed91c78849e..047221a8e4be2e 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -165,6 +165,9 @@ def test_color(self): out, err = self.run_cli(commands="\n") self.assertIn("\x1b[1;35msqlite> \x1b[0m", out) self.assertIn("\x1b[1;35m ... \x1b[0m\x1b", out) + out, err = self.run_cli(commands=("sel;",)) + self.assertIn('\x1b[1;35mOperationalError (SQLITE_ERROR)\x1b[0m: ' + '\x1b[35mnear "sel": syntax error\x1b[0m', err) if __name__ == "__main__": unittest.main() From ca015a1c9b87a477e450cc1ec7b95e30018e0ab7 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 6 May 2025 16:58:25 +0100 Subject: [PATCH 04/13] Now with themes! --- Lib/sqlite3/__main__.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index f2b6c8f93ebcb8..760f5dd448b284 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -12,11 +12,11 @@ from textwrap import dedent import _colorize as colorize -BOLD_MAGENTA = colorize.ANSIColors.BOLD_MAGENTA -MAGENTA =colorize.ANSIColors.MAGENTA +SYNTAX = colorize.Syntax +TRACEBACK=colorize.Traceback RESET = colorize.ANSIColors.RESET -def color(color, use_color): +def _clr(color, use_color): if use_color: return color return '' @@ -36,12 +36,12 @@ def execute(c, sql, suppress_errors=True, use_color=False): except sqlite3.Error as e: tp = type(e).__name__ try: - print(f"{color(BOLD_MAGENTA, use_color)}{tp} ({e.sqlite_errorname})" - f"{color(RESET, use_color)}: " - f"{color(MAGENTA, use_color)}{e}{color(RESET, use_color)}", file=sys.stderr) + print(f"{_clr(TRACEBACK.type, use_color)}{tp} ({e.sqlite_errorname})" + f"{_clr(RESET, use_color)}: " + f"{_clr(TRACEBACK.message, use_color)}{e}{_clr(RESET, use_color)}", file=sys.stderr) except AttributeError: - print(f"{color(BOLD_MAGENTA, use_color)}{tp}{color(RESET, use_color)}: " - f"{color(MAGENTA, use_color)}{e}{color(RESET, use_color)}", file=sys.stderr) + print(f"{_clr(TRACEBACK.type, use_color)}{tp}{_clr(RESET, use_color)}: " + f"{_clr(TRACEBACK.message, use_color)}{e}{_clr(RESET, use_color)}", file=sys.stderr) if not suppress_errors: sys.exit(1) @@ -121,8 +121,8 @@ def main(*args): use_color = colorize.can_colorize() - sys.ps1 = f"{color(BOLD_MAGENTA, use_color)}sqlite> {color(RESET, use_color)}" - sys.ps2 = f"{color(BOLD_MAGENTA, use_color)} ... {color(RESET, use_color)}" + sys.ps1 = f"{_clr(SYNTAX.prompt, use_color)}sqlite> {_clr(RESET, use_color)}" + sys.ps2 = f"{_clr(SYNTAX.prompt, use_color)} ... {_clr(RESET, use_color)}" con = sqlite3.connect(args.filename, isolation_level=None) try: From 2c060760aff56ba7b0f0a72175c28157fed99181 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 6 May 2025 17:03:19 +0100 Subject: [PATCH 05/13] Simpler usage --- Lib/sqlite3/__main__.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 760f5dd448b284..0756d23df7cd8d 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -12,10 +12,6 @@ from textwrap import dedent import _colorize as colorize -SYNTAX = colorize.Syntax -TRACEBACK=colorize.Traceback -RESET = colorize.ANSIColors.RESET - def _clr(color, use_color): if use_color: return color @@ -34,14 +30,15 @@ def execute(c, sql, suppress_errors=True, use_color=False): for row in c.execute(sql): print(row) except sqlite3.Error as e: + theme = colorize.get_theme(force_color=True).traceback tp = type(e).__name__ try: - print(f"{_clr(TRACEBACK.type, use_color)}{tp} ({e.sqlite_errorname})" - f"{_clr(RESET, use_color)}: " - f"{_clr(TRACEBACK.message, use_color)}{e}{_clr(RESET, use_color)}", file=sys.stderr) + print(f"{_clr(theme.type, use_color)}{tp} ({e.sqlite_errorname})" + f"{_clr(theme.reset, use_color)}: " + f"{_clr(theme.message, use_color)}{e}{_clr(theme.RESET, use_color)}", file=sys.stderr) except AttributeError: - print(f"{_clr(TRACEBACK.type, use_color)}{tp}{_clr(RESET, use_color)}: " - f"{_clr(TRACEBACK.message, use_color)}{e}{_clr(RESET, use_color)}", file=sys.stderr) + print(f"{_clr(theme.type, use_color)}{tp}{_clr(theme.RESET, use_color)}: " + f"{_clr(theme.message, use_color)}{e}{_clr(theme.RESET, use_color)}", file=sys.stderr) if not suppress_errors: sys.exit(1) @@ -120,9 +117,10 @@ def main(*args): """).strip() use_color = colorize.can_colorize() + theme = colorize.get_theme(force_color=True).syntax - sys.ps1 = f"{_clr(SYNTAX.prompt, use_color)}sqlite> {_clr(RESET, use_color)}" - sys.ps2 = f"{_clr(SYNTAX.prompt, use_color)} ... {_clr(RESET, use_color)}" + sys.ps1 = f"{_clr(theme.prompt, use_color)}sqlite> {_clr(theme.RESET, use_color)}" + sys.ps2 = f"{_clr(theme.prompt, use_color)} ... {_clr(theme.RESET, use_color)}" con = sqlite3.connect(args.filename, isolation_level=None) try: From 198399e1d0f68eb0e35f30135c38eb46dd891f56 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 6 May 2025 17:42:25 +0100 Subject: [PATCH 06/13] Fixup --- Lib/sqlite3/__main__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 0756d23df7cd8d..4bf070e75f3de3 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -35,10 +35,10 @@ def execute(c, sql, suppress_errors=True, use_color=False): try: print(f"{_clr(theme.type, use_color)}{tp} ({e.sqlite_errorname})" f"{_clr(theme.reset, use_color)}: " - f"{_clr(theme.message, use_color)}{e}{_clr(theme.RESET, use_color)}", file=sys.stderr) + f"{_clr(theme.message, use_color)}{e}{_clr(theme.reset, use_color)}", file=sys.stderr) except AttributeError: - print(f"{_clr(theme.type, use_color)}{tp}{_clr(theme.RESET, use_color)}: " - f"{_clr(theme.message, use_color)}{e}{_clr(theme.RESET, use_color)}", file=sys.stderr) + print(f"{_clr(theme.type, use_color)}{tp}{_clr(theme.reset, use_color)}: " + f"{_clr(theme.message, use_color)}{e}{_clr(theme.reset, use_color)}", file=sys.stderr) if not suppress_errors: sys.exit(1) @@ -119,8 +119,8 @@ def main(*args): use_color = colorize.can_colorize() theme = colorize.get_theme(force_color=True).syntax - sys.ps1 = f"{_clr(theme.prompt, use_color)}sqlite> {_clr(theme.RESET, use_color)}" - sys.ps2 = f"{_clr(theme.prompt, use_color)} ... {_clr(theme.RESET, use_color)}" + sys.ps1 = f"{_clr(theme.prompt, use_color)}sqlite> {_clr(theme.reset, use_color)}" + sys.ps2 = f"{_clr(theme.prompt, use_color)} ... {_clr(theme.reset, use_color)}" con = sqlite3.connect(args.filename, isolation_level=None) try: From 2a8c72931466ac84c04b82e0157a51a5604bab88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Tue, 6 May 2025 20:34:13 +0200 Subject: [PATCH 07/13] Simplify --- Lib/sqlite3/__main__.py | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 4bf070e75f3de3..bd48e04b9b9f3d 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -10,14 +10,9 @@ from argparse import ArgumentParser from code import InteractiveConsole from textwrap import dedent -import _colorize as colorize +from _colorize import get_theme, theme_no_color -def _clr(color, use_color): - if use_color: - return color - return '' - -def execute(c, sql, suppress_errors=True, use_color=False): +def execute(c, sql, suppress_errors=True, theme=theme_no_color): """Helper that wraps execution of SQL code. This is used both by the REPL and by direct execution from the CLI. @@ -30,15 +25,16 @@ def execute(c, sql, suppress_errors=True, use_color=False): for row in c.execute(sql): print(row) except sqlite3.Error as e: - theme = colorize.get_theme(force_color=True).traceback + t = theme.traceback tp = type(e).__name__ try: - print(f"{_clr(theme.type, use_color)}{tp} ({e.sqlite_errorname})" - f"{_clr(theme.reset, use_color)}: " - f"{_clr(theme.message, use_color)}{e}{_clr(theme.reset, use_color)}", file=sys.stderr) + tp += f" ({e.sqlite_errorname})" except AttributeError: - print(f"{_clr(theme.type, use_color)}{tp}{_clr(theme.reset, use_color)}: " - f"{_clr(theme.message, use_color)}{e}{_clr(theme.reset, use_color)}", file=sys.stderr) + pass + print( + f"{t.type}{tp}{t.reset}: {t.message}{e}{t.reset}", + file=sys.stderr, + ) if not suppress_errors: sys.exit(1) @@ -68,7 +64,8 @@ def runsource(self, source, filename="", symbol="single"): case _: if not sqlite3.complete_statement(source): return True - execute(self._cur, source, use_color=self._use_color) + theme = get_theme(force_no_color=not self._use_color) + execute(self._cur, source, theme=theme) return False @@ -116,11 +113,10 @@ def main(*args): Type ".help" for more information; type ".quit" or {eofkey} to quit. """).strip() - use_color = colorize.can_colorize() - theme = colorize.get_theme(force_color=True).syntax + s = get_theme().syntax - sys.ps1 = f"{_clr(theme.prompt, use_color)}sqlite> {_clr(theme.reset, use_color)}" - sys.ps2 = f"{_clr(theme.prompt, use_color)} ... {_clr(theme.reset, use_color)}" + sys.ps1 = f"{s.prompt}sqlite> {s.reset}" + sys.ps2 = f"{s.prompt} ... {s.reset}" con = sqlite3.connect(args.filename, isolation_level=None) try: @@ -129,7 +125,7 @@ def main(*args): execute(con, args.sql, suppress_errors=False) else: # No SQL provided; start the REPL. - console = SqliteInteractiveConsole(con, use_color) + console = SqliteInteractiveConsole(con, use_color=True) try: import readline # noqa: F401 except ImportError: From a220442e7ed52a38c0a45f97ce61057e2b6946c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Tue, 6 May 2025 20:45:58 +0200 Subject: [PATCH 08/13] Don't skip coloring errors on single-statement execution --- Lib/sqlite3/__main__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index bd48e04b9b9f3d..099637230814dc 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -113,7 +113,8 @@ def main(*args): Type ".help" for more information; type ".quit" or {eofkey} to quit. """).strip() - s = get_theme().syntax + theme = get_theme() + s = theme.syntax sys.ps1 = f"{s.prompt}sqlite> {s.reset}" sys.ps2 = f"{s.prompt} ... {s.reset}" @@ -122,7 +123,7 @@ def main(*args): try: if args.sql: # SQL statement provided on the command-line; execute it directly. - execute(con, args.sql, suppress_errors=False) + execute(con, args.sql, suppress_errors=False, theme=theme) else: # No SQL provided; start the REPL. console = SqliteInteractiveConsole(con, use_color=True) From e65d724a18b659912d767441516d500a8bc81cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Tue, 6 May 2025 21:00:44 +0200 Subject: [PATCH 09/13] Also ignore color in the CLI test case --- Lib/test/test_sqlite3/test_cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index 047221a8e4be2e..ac2c2b75a0afc8 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -13,6 +13,7 @@ ) +@force_not_colorized_test_class class CommandLineInterface(unittest.TestCase): def _do_test(self, *args, expect_success=True): From 66711a04bae7295771806c2bea91b6c0a20624cc Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 6 May 2025 20:03:33 +0100 Subject: [PATCH 10/13] Clean up --- Lib/sqlite3/__main__.py | 3 +-- Lib/test/test_sqlite3/test_cli.py | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 099637230814dc..a21d21a737fb88 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -32,8 +32,7 @@ def execute(c, sql, suppress_errors=True, theme=theme_no_color): except AttributeError: pass print( - f"{t.type}{tp}{t.reset}: {t.message}{e}{t.reset}", - file=sys.stderr, + f"{t.type}{tp}{t.reset}: {t.message}{e}{t.reset}", file=sys.stderr ) if not suppress_errors: sys.exit(1) diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index ac2c2b75a0afc8..d44baee4c89cb5 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -8,7 +8,6 @@ captured_stdout, captured_stderr, captured_stdin, - force_not_colorized, force_not_colorized_test_class, ) @@ -39,7 +38,6 @@ def expect_failure(self, *args): self.assertEqual(out, "") return err - @force_not_colorized def test_cli_help(self): out = self.expect_success("-h") self.assertIn("usage: ", out) From 62a0164e700476d006a0a1386f2cf38e247ffd3a Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Wed, 7 May 2025 20:27:48 +0100 Subject: [PATCH 11/13] Fix line removal Co-authored-by: Erlend E. Aasland --- Lib/sqlite3/__main__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index a21d21a737fb88..a1993c4190f00c 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -12,6 +12,7 @@ from textwrap import dedent from _colorize import get_theme, theme_no_color + def execute(c, sql, suppress_errors=True, theme=theme_no_color): """Helper that wraps execution of SQL code. From 4ed58156cde78c737a1ba81bc11d0d2f12c247c7 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Fri, 9 May 2025 17:39:59 +0100 Subject: [PATCH 12/13] Lint --- Lib/sqlite3/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 4c72a631368014..c2fa23c46cf990 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -55,7 +55,7 @@ def runsource(self, source, filename="", symbol="single"): Return False if input is a complete statement ready for execution. """ theme = get_theme(force_no_color=not self._use_color) - + if not source or source.isspace(): return False if source[0] == ".": From 4c0b52c3d20b64917d0fcba47224b320022cee14 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Sat, 10 May 2025 08:30:34 +0100 Subject: [PATCH 13/13] fixup! Lint --- Lib/test/test_sqlite3/test_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index a3c8b05c93371a..37e0f74f688659 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -193,7 +193,7 @@ def test_interact_on_disk_file(self): def test_color(self): with unittest.mock.patch("_colorize.can_colorize", return_value=True): - out, err = self.run_cli(commands="\n") + out, err = self.run_cli(commands="TEXT\n") self.assertIn("\x1b[1;35msqlite> \x1b[0m", out) self.assertIn("\x1b[1;35m ... \x1b[0m\x1b", out) out, err = self.run_cli(commands=("sel;",))