Ticket #656 (closed defect: fixed)

Opened 10 years ago

Last modified 7 years ago

pex::exceptions are not correctly caught from interactive python

Reported by: rhl Owned by: ktl
Priority: normal Milestone:
Component: pex_exceptions Keywords:
Cc: Blocked By:
Blocking: Project: LSST
Version Number:
How to repeat:

Checkout and build source:DMS/pex/exceptions/tickets/656, then

$ cd tests
$ python
>>> import ticket656; ticket656.run()

Description

It is possible to generate pex::exceptions that are caught correctly when sourced as a python script, but which fail when imported:

Traceback (most recent call last):
  File "ticketXXX.py", line 27, in testFail2
    print e
  File "/u/lsst/products/DarwinX86/pex_exceptions/3.2.1/python/lsst/pex/exceptions/exceptionsLib.py", line 62, in __str__
    return self.args[0].what()
IndexError: tuple index out of range

Change History

comment:1 Changed 10 years ago by rhl

  • How to repeat modified (diff)

comment:2 Changed 10 years ago by rhl

  • How to repeat modified (diff)

comment:3 Changed 10 years ago by ktl

  • Status changed from new to assigned

comment:4 Changed 10 years ago by ktl

  • Owner changed from ktl to rhl
  • Status changed from assigned to needinfo

If you replace the raiseLsstException() function in p_lsstSwig.i (or pex/exceptions/tests/Failer.i) with this, do things work properly?

static void raiseLsstException(lsst::pex::exceptions::Exception& ex) {
    PyObject* pyex = 0;
    char const* t = ex.getType();
    swig_type_info* tinfo = SWIG_TypeQuery(t);
    if (tinfo == 0) {
        char* swigt = new char[strlen(t) + 2];
        swigt[0] = swigt[2] = '_'; swigt[1] = 'p';
        char* cp = swigt + 3;
        while (*t != ' ') {
            if (*t == ':') *cp = '_';
            else *cp = *t;
            ++t;
            ++cp;
        }
        *cp = '\0';
        tinfo = SWIG_TypeQuery(swigt);
        delete[] swigt;
    }
    if (tinfo != 0) {
        lsst::pex::exceptions::Exception* e = ex.clone();
        pyex = SWIG_NewPointerObj(static_cast<void*>(e), tinfo,
            SWIG_POINTER_OWN);
    }
    else {
        pyex = Py_None;
    }

    PyObject* pyexbase = PyExc_RuntimeError;
    PyObject* module = PyImport_AddModule("lsst.pex.exceptions");
    if (module != 0) {
        pyexbase = PyObject_GetAttrString(module, "LsstCppException");
        if (pyexbase == 0) {
            pyexbase = PyExc_RuntimeError;
        }
    }

    PyErr_SetObject(pyexbase, pyex);
}

comment:5 Changed 10 years ago by ktl

  • Owner changed from rhl to ktl
  • Status changed from needinfo to assigned

comment:6 Changed 10 years ago by ktl

  • Status changed from assigned to closed
  • Resolution set to fixed

Fixed in a better way by adding %types directives to exceptionsLib.i to ensure that the runtime exception types are always available to be looked up by the raiseLsstException() code. The how-to-repeat was converted into a test case. Merged to trunk in [7531].

comment:7 Changed 10 years ago by ktl

P.S. See the SWIG documentation for details on %types. Note that we can't use $1_descriptor or $descriptor() because the exception object type is only known at runtime, not wrap time.

comment:8 Changed 7 years ago by robyn

  • Milestone DC3a Apps Framework deleted

Milestone DC3a Apps Framework deleted

Note: See TracTickets for help on using tickets.