Mercurial > cpython-lru_cache-weakref
diff Python/bltinmodule.c @ 11030:3be935be3781 legacy-trunk
Patch by Tim Peters:
Introduce a new builtin exception, UnboundLocalError, raised when ceval.c
tries to retrieve or delete a local name that isn't bound to a value.
Currently raises NameError, which makes this behavior a FAQ since the same
error is raised for "missing" global names too: when the user has a global
of the same name as the unbound local, NameError makes no sense to them.
Even in the absence of shadowing, knowing whether a bogus name is local or
global is a real aid to quick understanding.
Example:
D:\src\PCbuild>type local.py
x = 42
def f():
print x
x = 13
return x
f()
D:\src\PCbuild>python local.py
Traceback (innermost last):
File "local.py", line 8, in ?
f()
File "local.py", line 4, in f
print x
UnboundLocalError: x
D:\src\PCbuild>
Note that UnboundLocalError is a subclass of NameError, for compatibility
with existing class-exception code that may be trying to catch this as a
NameError. Unfortunately, I see no way to make this wholly compatible
with -X (see comments in bltinmodule.c): under -X, [UnboundLocalError
is an alias for NameError --GvR].
[The ceval.c patch differs slightly from the second version that Tim
submitted; I decided not to raise UnboundLocalError for DELETE_NAME,
only for DELETE_LOCAL. DELETE_NAME is only generated at the module
level, and since at that level a NameError is raised for referencing
an undefined name, it should also be raised for deleting one.]
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Tue, 22 Jun 1999 14:47:32 +0000 |
| parents | e9442734bc49 |
| children | 41a46978a444 |
line wrap: on
line diff
--- a/Python/bltinmodule.c Mon Jun 21 22:36:53 1999 +0000 +++ b/Python/bltinmodule.c Tue Jun 22 14:47:32 1999 +0000 @@ -2232,6 +2232,7 @@ PyObject *PyExc_SyntaxError; PyObject *PyExc_SystemError; PyObject *PyExc_SystemExit; +PyObject *PyExc_UnboundLocalError; PyObject *PyExc_TypeError; PyObject *PyExc_ValueError; PyObject *PyExc_ZeroDivisionError; @@ -2261,6 +2262,11 @@ {"KeyError", &PyExc_KeyError, 1}, {"KeyboardInterrupt", &PyExc_KeyboardInterrupt, 1}, {"MemoryError", &PyExc_MemoryError, 1}, + /* Note: NameError is not a leaf in exceptions.py, but unlike + the other non-leafs NameError is meant to be raised directly + at times -- the leaf_exc member really seems to mean something + like "this is an abstract base class" when false. + */ {"NameError", &PyExc_NameError, 1}, {"OverflowError", &PyExc_OverflowError, 1}, {"RuntimeError", &PyExc_RuntimeError, 1}, @@ -2268,6 +2274,7 @@ {"SyntaxError", &PyExc_SyntaxError, 1}, {"SystemError", &PyExc_SystemError, 1}, {"SystemExit", &PyExc_SystemExit, 1}, + {"UnboundLocalError", &PyExc_UnboundLocalError, 1}, {"TypeError", &PyExc_TypeError, 1}, {"ValueError", &PyExc_ValueError, 1}, {"ZeroDivisionError", &PyExc_ZeroDivisionError, 1}, @@ -2420,6 +2427,14 @@ PyTuple_SET_ITEM(PyExc_EnvironmentError, 1, PyExc_OSError); PyDict_SetItemString(dict, "EnvironmentError", PyExc_EnvironmentError); + /* Make UnboundLocalError an alias for NameError */ + Py_INCREF(PyExc_NameError); + Py_DECREF(PyExc_UnboundLocalError); + PyExc_UnboundLocalError = PyExc_NameError; + if (PyDict_SetItemString(dict, "UnboundLocalError", + PyExc_NameError) != 0) + Py_FatalError("Cannot create string-based exceptions"); + /* missing from the StandardError tuple: Exception, StandardError, * and SystemExit */
