diff --git a/Lib/sqlite3/__main__.py b/Lib/sqlite3/__main__.py index ec72c6943907175..6065a4ea923f5d8 100644 --- a/Lib/sqlite3/__main__.py +++ b/Lib/sqlite3/__main__.py @@ -15,6 +15,13 @@ from ._completer import completer +# IDLE uses CTRL-D for EOF on all platforms (gh-102628). +if sys.platform == "win32" and "idlelib.run" not in sys.modules: + EOF_KEY = "CTRL-Z" +else: + EOF_KEY = "CTRL-D" + + def execute(c, sql, suppress_errors=True, theme=theme_no_color): """Helper that wraps execution of SQL code. @@ -70,7 +77,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 "": @@ -115,16 +122,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 e049d16642ce0ca..2dced0ee1f52753 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -82,6 +82,7 @@ class InteractiveSession(unittest.TestCase): MEMORY_DB_MSG = "Connected to a transient in-memory database" PS1 = "\001\002sqlite> \001\002" PS2 = "\001\002 ... \001\002" + EOF_KEY = "CTRL-Z" if sys.platform == "win32" else "CTRL-D" def run_cli(self, *args, commands=()): with ( @@ -104,11 +105,19 @@ def run_cli(self, *args, commands=()): def test_interact(self): out, err = self.run_cli() self.assertIn(self.MEMORY_DB_MSG, err) - self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn(f'type ".quit" or {self.EOF_KEY} to quit', err) self.assertEndsWith(out, self.PS1) self.assertEqual(out.count(self.PS1), 1) self.assertEqual(out.count(self.PS2), 0) + def test_interact_help(self): + out, err = self.run_cli(commands=(".help",)) + self.assertIn(self.MEMORY_DB_MSG, err) + self.assertIn(f"Exit the CLI, equivalent to {self.EOF_KEY}", 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 000000000000000..0494a66b094eee9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-09-18-18-03-32.gh-issue-139105.1QQ_W4.rst @@ -0,0 +1 @@ +Correct the EOF key shown in the :mod:`sqlite3` CLI ``.help`` text on Windows.