Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Lib/test/test_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,5 +835,23 @@ def g(self, __arg):
with self.assertRaises(TypeError):
closure(_MultiplyNested__arg=2)

def test_builtin_deletion_err_message(self):
with self.assertRaisesRegex(NameError, "cannot delete builtin 'all'"):
del all

def f():
del all

with self.assertRaisesRegex(UnboundLocalError, "cannot delete builtin 'all'"):
f()

def g():
global all
del all

with self.assertRaisesRegex(NameError, "cannot delete builtin 'all'"):
g()


if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deleting built-in names with :keyword:`del` now gives a clearer error message.
32 changes: 23 additions & 9 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1577,9 +1577,13 @@ dummy_func(
err = PyObject_DelItem(ns, name);
// Can't use ERROR_IF here.
if (err != 0) {
_PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
NAME_ERROR_MSG,
name);
if (PyMapping_HasKeyWithError(BUILTINS(), name) == 1) {
_PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
CANNOT_DELETE_BUILTIN_ERROR_MSG, name);
} else {
_PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
ERROR_NO_POP();
}
}
Expand Down Expand Up @@ -1720,8 +1724,13 @@ dummy_func(
ERROR_NO_POP();
}
if (err == 0) {
_PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
if (PyMapping_HasKeyWithError(BUILTINS(), name) == 1) {
_PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
CANNOT_DELETE_BUILTIN_ERROR_MSG, name);
} else {
_PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
ERROR_NO_POP();
}
}
Expand Down Expand Up @@ -1888,10 +1897,15 @@ dummy_func(
inst(DELETE_FAST, (--)) {
_PyStackRef v = GETLOCAL(oparg);
if (PyStackRef_IsNull(v)) {
_PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg)
);
PyObject *localsplusnames = _PyFrame_GetCode(frame)->co_localsplusnames;
PyObject *name = PyTuple_GetItem(localsplusnames, oparg);
if (PyMapping_HasKeyWithError(BUILTINS(), name) == 1) {
_PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError,
CANNOT_DELETE_BUILTIN_ERROR_MSG, name);
} else {
_PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG, name);
}
ERROR_IF(true);
}
_PyStackRef tmp = GETLOCAL(oparg);
Expand Down
1 change: 1 addition & 0 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
"cannot access free variable '%s' where it is not associated with a value" \
" in enclosing scope"
#define NAME_ERROR_MSG "name '%.200s' is not defined"
#define CANNOT_DELETE_BUILTIN_ERROR_MSG "cannot delete builtin '%.200s'"

// If a trace function sets a new f_lineno and
// *then* raises, we use the destination when searching
Expand Down
48 changes: 35 additions & 13 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 35 additions & 13 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading