Skip to content

Commit 854933d

Browse files
committed
bpo-44603: Exit the interpreter if the user types "exit"
1 parent 2f180ce commit 854933d

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

Doc/whatsnew/3.11.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,14 @@ New Modules
9898
Improved Modules
9999
================
100100

101+
builtins
102+
--------
103+
104+
* In the interactive REPL, typing "exit" or "quit" will directly exit the
105+
interpreter session instead of printing a message suggesting to use "exit()" or
106+
"quit()" instead. Contributed by Pablo Galindo in :issue:`44603`.
107+
108+
101109
fractions
102110
---------
103111

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
In the interactive REPL, typing "exit" or "quit" will directly exit the
2+
interpreter session instead of printing a message suggesting to use "exit()"
3+
or "quit()" instead. Patch by Pablo Galindo

Python/pythonrun.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,25 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flag
188188

189189
}
190190

191+
static int
192+
PyRun_IsInteractiveExitCommand(mod_ty mod) {
193+
if (asdl_seq_LEN(mod->v.Module.body) != 1) {
194+
return 0;
195+
}
196+
stmt_ty statement = asdl_seq_GET(mod->v.Module.body, 0);
197+
if (statement->kind != Expr_kind) {
198+
return 0;
199+
}
200+
expr_ty expr = statement->v.Expr.value;
201+
if (expr->kind != Name_kind) {
202+
return 0;
203+
}
204+
if (expr->v.Name.ctx != Load) {
205+
return 0;
206+
}
207+
return PyUnicode_CompareWithASCIIString(expr->v.Name.id, "exit") == 0 ||
208+
PyUnicode_CompareWithASCIIString(expr->v.Name.id, "quit") == 0;
209+
}
191210

192211
/* A PyRun_InteractiveOneObject() auxiliary function that does not print the
193212
* error on failure. */
@@ -267,6 +286,14 @@ PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,
267286
}
268287
return -1;
269288
}
289+
290+
if (PyRun_IsInteractiveExitCommand(mod)) {
291+
Py_INCREF(Py_None);
292+
PyErr_SetObject(PyExc_SystemExit, Py_None);
293+
_PyArena_Free(arena);
294+
return -1;
295+
}
296+
270297
m = PyImport_AddModuleObject(mod_name);
271298
if (m == NULL) {
272299
_PyArena_Free(arena);

0 commit comments

Comments
 (0)