Added Py_UseClassExceptionsFlag, the variable containing the state of

the -X command line option.

Py_Initialize(): Handle the two phase initialization of the built-in
module.

Py_Finalize(): Handle the two phase finalization of the built-in
module.

parse_syntax_error(): New function which parses syntax errors that
PyErr_Print() will catch.  This correctly parses such errors
regardless of whether PyExc_SyntaxError is an old-style string
exception or new-fangled class exception.

PyErr_Print(): Many changes:

    1. Normalize the exception.

    2. Handle SystemExit exceptions which might be class based.  Digs
       the exit code out of the "code" attribute.  String based
       SystemExit is handled the same as before.

    3. Handle SyntaxError exceptions which might be class based.  Digs
       the various information bits out of the instance's attributes
       (see parse_syntax_error() for details).  String based
       SyntaxError still works too.

    4. Don't write the `:' after the exception if the exception is
       class based and has an empty string str() value.
This commit is contained in:
Barry Warsaw 1997-08-29 22:07:17 +00:00
parent d5a0ff972d
commit 035574d755
1 changed files with 106 additions and 5 deletions

View File

@ -75,6 +75,7 @@ static void call_ll_exitfuncs Py_PROTO((void));
int Py_DebugFlag; /* Needed by parser.c */
int Py_VerboseFlag; /* Needed by import.c */
int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */
int Py_UseClassExceptionsFlag; /* Needed by bltinmodule.c */
static int initialized = 0;
@ -127,7 +128,7 @@ Py_Initialize()
if (interp->modules == NULL)
Py_FatalError("Py_Initialize: can't make modules dictionary");
bimod = _PyBuiltin_Init();
bimod = _PyBuiltin_Init_1();
if (bimod == NULL)
Py_FatalError("Py_Initialize: can't initialize __builtin__");
interp->builtins = PyModule_GetDict(bimod);
@ -144,6 +145,9 @@ Py_Initialize()
PyDict_SetItemString(interp->sysdict, "modules",
interp->modules);
/* phase 2 of builtins */
_PyBuiltin_Init_2(interp->builtins);
_PyImport_Init();
initsigs(); /* Signal handling stuff, including initintr() */
@ -178,6 +182,12 @@ Py_Finalize()
if (initialized < 0)
Py_FatalError("Py_Finalize: not initialized");
/* We must call this before the current thread gets removed because
it decrefs class instances, which in turn save and restore the
current error state, which is a per thread data structure.
*/
_PyBuiltin_Fini_1();
tstate = PyThreadState_Get();
interp = tstate->interp;
@ -188,7 +198,13 @@ Py_Finalize()
finisigs();
_PyImport_Fini();
_PyBuiltin_Fini();
/* Now we decref the exception classes. After this point nothing
can raise an exception. That's okay, because each Fini() method
below has been checked to make sure no exceptions are ever
raised.
*/
_PyBuiltin_Fini_2();
PyMethod_Fini();
PyFrame_Fini();
PyCFunction_Fini();
@ -522,19 +538,99 @@ PyRun_SimpleString(command)
return 0;
}
static int
parse_syntax_error(err, message, filename, lineno, offset, text)
PyObject* err;
PyObject** message;
char** filename;
int* lineno;
int* offset;
char** text;
{
long hold;
PyObject *v;
/* old style errors */
if (PyTuple_Check(err))
return PyArg_Parse(err, "(O(ziiz))", message, filename,
lineno, offset, text);
/* new style errors. `err' is an instance */
if (! (v = PyObject_GetAttrString(err, "msg")))
goto finally;
*message = v;
if (!(v = PyObject_GetAttrString(err, "filename")))
goto finally;
if (v == Py_None)
*filename = NULL;
else if (! (*filename = PyString_AsString(v)))
goto finally;
Py_DECREF(v);
if (!(v = PyObject_GetAttrString(err, "lineno")))
goto finally;
hold = PyInt_AsLong(v);
Py_DECREF(v);
v = NULL;
if (hold < 0 && PyErr_Occurred())
goto finally;
*lineno = (int)hold;
if (!(v = PyObject_GetAttrString(err, "offset")))
goto finally;
hold = PyInt_AsLong(v);
Py_DECREF(v);
v = NULL;
if (hold < 0 && PyErr_Occurred())
goto finally;
*offset = (int)hold;
if (!(v = PyObject_GetAttrString(err, "text")))
goto finally;
if (v == Py_None)
*text = NULL;
else if (! (*text = PyString_AsString(v)))
goto finally;
Py_DECREF(v);
return 1;
finally:
Py_XDECREF(v);
return 0;
}
void
PyErr_Print()
{
int err = 0;
PyObject *exception, *v, *tb, *f;
PyErr_Fetch(&exception, &v, &tb);
PyErr_NormalizeException(&exception, &v, &tb);
if (exception == NULL)
return;
if (PyErr_GivenExceptionMatches(exception, PyExc_SystemExit)) {
err = Py_FlushLine();
fflush(stdout);
if (v == NULL || v == Py_None)
Py_Exit(0);
if (PyInstance_Check(v)) {
/* we expect the error code to be store in the
`code' attribute
*/
PyObject *code = PyObject_GetAttrString(v, "code");
if (code) {
Py_DECREF(v);
v = code;
}
/* if we failed to dig out the "code" attribute,
then just let the else clause below print the
error
*/
}
if (PyInt_Check(v))
Py_Exit((int)PyInt_AsLong(v));
else {
@ -561,8 +657,8 @@ PyErr_Print()
PyObject *message;
char *filename, *text;
int lineno, offset;
if (!PyArg_Parse(v, "(O(ziiz))", &message,
&filename, &lineno, &offset, &text))
if (!parse_syntax_error(v, &message, &filename,
&lineno, &offset, &text))
PyErr_Clear();
else {
char buf[10];
@ -630,7 +726,12 @@ PyErr_Print()
err = PyFile_WriteObject(exception, f, Py_PRINT_RAW);
if (err == 0) {
if (v != NULL && v != Py_None) {
err = PyFile_WriteString(": ", f);
PyObject *s = PyObject_Str(v);
/* only print colon if the str() of the
object is not the empty string
*/
if (s && strcmp(PyString_AsString(s), ""))
err = PyFile_WriteString(": ", f);
if (err == 0)
err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
}