From 95723d09d2ae2321b000acdc0a513ab27c5646e7 Mon Sep 17 00:00:00 2001 From: Keming Date: Thu, 18 Sep 2025 18:05:20 +0800 Subject: [PATCH 1/4] gh-139105: Fix the EOF key shows on Windows for .help command Signed-off-by: Keming --- Lib/sqlite3/__main__.py | 15 ++++++---- Lib/test/test_sqlite3/test_cli.py | 28 +++++++++++++++++++ ...-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst | 1 + 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 35344ecceff526..3b217785a31eab 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -41,6 +41,13 @@ def execute(c, sql, suppress_errors=True, theme=theme_no_color): sys.exit(1) +def _eof_key(): + if sys.platform == "win32" and "idlelib.run" not in sys.modules: + return "CTRL-Z" + else: + return "CTRL-D" + + class SqliteInteractiveConsole(InteractiveConsole): """A simple SQLite REPL.""" @@ -69,7 +76,7 @@ def runsource(self, source, filename="", symbol="single"): print(f"Enter SQL code or one of the below commands, and press enter.\n\n" f"{t.builtin}.version{t.reset} Print underlying SQLite library version\n" f"{t.builtin}.help{t.reset} Print this help message\n" - f"{t.builtin}.quit{t.reset} Exit the CLI, equivalent to CTRL-D\n") + f"{t.builtin}.quit{t.reset} Exit the CLI, equivalent to {_eof_key()}\n") case "quit": sys.exit(0) case "": @@ -117,16 +124,12 @@ def main(*args): db_name = repr(args.filename) # Prepare REPL banner and prompts. - if sys.platform == "win32" and "idlelib.run" not in sys.modules: - eofkey = "CTRL-Z" - else: - eofkey = "CTRL-D" banner = dedent(f""" sqlite3 shell, running on SQLite version {sqlite3.sqlite_version} Connected to {db_name} Each command will be run using execute() on the cursor. - Type ".help" for more information; type ".quit" or {eofkey} to quit. + Type ".help" for more information; type ".quit" or {_eof_key()} to quit. """).strip() theme = get_theme() diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index 720fa3c4c1ea8b..1429946a4e812a 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -109,6 +109,34 @@ def test_interact(self): self.assertEqual(out.count(self.PS1), 1) self.assertEqual(out.count(self.PS2), 0) + @unittest.skipUnless(sys.platform == "win32", "Windows EOF is CTRL-Z") + def test_interact_banner_win(self): + _, err = self.run_cli() + self.assertIn('type ".quit" or CTRL-Z to quit', err) + + @unittest.skipUnless(sys.platform != "win32", "Non-Windows EOF is CTRL-D") + def test_interact_banner_non_win(self): + _, err = self.run_cli() + self.assertIn('type ".quit" or CTRL-D to quit', err) + + @unittest.skipUnless(sys.platform == "win32", "Windows EOF is CTRL-Z") + def test_interact_help_eof_win(self): + out, err = self.run_cli(commands=(".help",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn("Exit the CLI, equivalent to CTRL-Z", out) + self.assertEndsWith(out, self.PS1) + self.assertEqual(out.count(self.PS1), 2) + self.assertEqual(out.count(self.PS2), 0) + + @unittest.skipUnless(sys.platform != "win32", "Non-Windows EOF is CTRL-D") + def test_interact_help_eof_non_win(self): + out, err = self.run_cli(commands=(".help",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn("Exit the CLI, equivalent to CTRL-D", out) + self.assertEndsWith(out, self.PS1) + self.assertEqual(out.count(self.PS1), 2) + self.assertEqual(out.count(self.PS2), 0) + def test_interact_quit(self): out, err = self.run_cli(commands=(".quit",)) self.assertIn(self.MEMORY_DB_MSG, err) diff --git a/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst b/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst new file mode 100644 index 00000000000000..a6fa3605960d32 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst @@ -0,0 +1 @@ +Fix the EOF key shows in sqlite3 `.help` command on Windows. From a6e2f6de556de0b25ee15e61887166574684b7b1 Mon Sep 17 00:00:00 2001 From: Keming Date: Thu, 18 Sep 2025 18:16:23 +0800 Subject: [PATCH 2/4] fix misc lint Signed-off-by: Keming --- .../next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst b/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst index a6fa3605960d32..59242948397c7a 100644 --- a/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst +++ b/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst @@ -1 +1 @@ -Fix the EOF key shows in sqlite3 `.help` command on Windows. +Fix the EOF key shows in sqlite3 ``.help`` command on Windows. From 13338fffb2b17c70cee15dc4e34380c533eccec0 Mon Sep 17 00:00:00 2001 From: Keming Date: Thu, 18 Sep 2025 23:13:44 +0800 Subject: [PATCH 3/4] use a global const to store the EOF key Signed-off-by: Keming --- Lib/sqlite3/__main__.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index 3b217785a31eab..80f0d1250e045e 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -15,6 +15,9 @@ from ._completer import completer +EOF_KEY = "CTRL-Z" if sys.platform == "win32" else "CTRL-D" + + def execute(c, sql, suppress_errors=True, theme=theme_no_color): """Helper that wraps execution of SQL code. @@ -41,13 +44,6 @@ def execute(c, sql, suppress_errors=True, theme=theme_no_color): sys.exit(1) -def _eof_key(): - if sys.platform == "win32" and "idlelib.run" not in sys.modules: - return "CTRL-Z" - else: - return "CTRL-D" - - class SqliteInteractiveConsole(InteractiveConsole): """A simple SQLite REPL.""" @@ -76,7 +72,7 @@ def runsource(self, source, filename="", symbol="single"): print(f"Enter SQL code or one of the below commands, and press enter.\n\n" f"{t.builtin}.version{t.reset} Print underlying SQLite library version\n" f"{t.builtin}.help{t.reset} Print this help message\n" - f"{t.builtin}.quit{t.reset} Exit the CLI, equivalent to {_eof_key()}\n") + f"{t.builtin}.quit{t.reset} Exit the CLI, equivalent to {EOF_KEY}\n") case "quit": sys.exit(0) case "": @@ -129,7 +125,7 @@ def main(*args): Connected to {db_name} Each command will be run using execute() on the cursor. - Type ".help" for more information; type ".quit" or {_eof_key()} to quit. + Type ".help" for more information; type ".quit" or {EOF_KEY} to quit. """).strip() theme = get_theme() From 18398aba2e3d45986e39192b8dc18d33b0e7b235 Mon Sep 17 00:00:00 2001 From: Keming Date: Thu, 18 Sep 2025 23:14:32 +0800 Subject: [PATCH 4/4] update misc news content Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- .../next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst b/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst index 59242948397c7a..0ffd4488742573 100644 --- a/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst +++ b/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst @@ -1 +1 @@ -Fix the EOF key shows in sqlite3 ``.help`` command on Windows. +Correct the EOF key shown in the :mod:`sqlite3` CLI ``.help`` text on Windows.