EpetraExt::ModelEvaluator::DerivativeSupport
getDerivativeSupportItemObjectAttr(PyObject * object, CONST char * name, int i)
{
    // The DerivativeSupport python class object
    static
    PyObject * classDerivativeSupport = NULL;
    if (!classDerivativeSupport)
    {
        classDerivativeSupport = getClassFromModule(PyTrilinosEpetraExt, "DerivativeSupport");
        if (!classDerivativeSupport) throw PythonException();
    }
    // Get the item from the object attribute
    PyObject * tuple = getTupleObjectAttr(object, name);
    PyObject * item  = PyTuple_GetItem(tuple, i);
    Py_DECREF(tuple);
    if (!item) throw PythonException();
    if (!PyObject_IsInstance(item, classDerivativeSupport))
    {
        PyErr_Format(PyExc_TypeError, "Attribute '%s' is not tuple of DerivativeSupport", name);
        Py_DECREF(item);
        throw PythonException();
    }
    EpetraExt::ModelEvaluator::EDerivativeLinearOp linearOp;
    EpetraExt::ModelEvaluator::EDerivativeMultiVectorOrientation orientation;
    EpetraExt::ModelEvaluator::DerivativeSupport result;
    if (getBoolObjectAttr(item, "linearOp"))
        result.plus(EpetraExt::ModelEvaluator::DERIV_LINEAR_OP);
    if (getBoolObjectAttr(item, "mVByCol"))
        result.plus(EpetraExt::ModelEvaluator::DERIV_MV_BY_COL);
    if (getBoolObjectAttr(item, "transMVByRow"))
        result.plus(EpetraExt::ModelEvaluator::DERIV_TRANS_MV_BY_ROW);
    Py_DECREF(item);
    return result;
}
Teuchos::RCP< const Epetra_Vector >
getConstEpetraVectorItemObjectAttr(PyObject   * object,
                                   CONST char * name,
                                   int          i)
{
  static swig_type_info * swig_EV_ptr =
    SWIG_TypeQuery("Teuchos::RCP< Epetra_Vector > *");
  void * argp;
  PyObject * tuple = getTupleObjectAttr(object, name);
  PyObject * item  = PyTuple_GetItem(tuple, i);
  Py_DECREF(tuple);
  if (!item) throw PythonException();
  int newmem = 0;
  if (!SWIG_CheckState(SWIG_Python_ConvertPtrAndOwn(item, &argp, swig_EV_ptr, 0, &newmem)))
  {
    PyErr_Format(PyExc_TypeError,
                 "Attribute '%s' is not tuple of type Epetra.Vector",
                 name);
    Py_DECREF(item);
    throw PythonException();
  }
  Teuchos::RCP< const Epetra_Vector > result =
    *reinterpret_cast< Teuchos::RCP< const Epetra_Vector > * >(argp);
  if (newmem)
    delete reinterpret_cast< Teuchos::RCP< const Epetra_Vector > * >(argp);
  Py_DECREF(item);
  return result;
}
EpetraExt::ModelEvaluator::DerivativeProperties
getDerivativePropertiesItemObjectAttr(PyObject * object, CONST char * name, int i)
{
    // The DerivativeProperties python class object
    static
    PyObject * classDerivativeProperties = NULL;
    if (!classDerivativeProperties)
    {
        classDerivativeProperties = getClassFromModule(PyTrilinosEpetraExt, "DerivativeProperties");
        if (!classDerivativeProperties) throw PythonException();
    }
    // Get the item from the object attribute
    PyObject * tuple = getTupleObjectAttr(object, name);
    PyObject * item  = PyTuple_GetItem(tuple, i);
    Py_DECREF(tuple);
    if (!item) throw PythonException();
    if (!PyObject_IsInstance(item, classDerivativeProperties))
    {
        PyErr_Format(PyExc_TypeError, "Attribute '%s' is not tuple of DerivativeProperties", name);
        Py_DECREF(item);
        throw PythonException();
    }
    EpetraExt::ModelEvaluator::DerivativeProperties result;
    // linearity attribute
    CONST char * linearity = getStringObjectAttr(item, "linearity");
    if (strncmp(linearity, "unknown", 7) == 0)
        result.linearity = EpetraExt::ModelEvaluator::DERIV_LINEARITY_UNKNOWN;
    if (strncmp(linearity, "const", 5) == 0)
        result.linearity = EpetraExt::ModelEvaluator::DERIV_LINEARITY_CONST;
    if (strncmp(linearity, "nonconst", 8) == 0)
        result.linearity = EpetraExt::ModelEvaluator::DERIV_LINEARITY_NONCONST;
    // rank attribute
    CONST char * rank = getStringObjectAttr(item, "rank");
    if (strncmp(rank, "unknown", 7) == 0)
        result.rank = EpetraExt::ModelEvaluator::DERIV_RANK_UNKNOWN;
    if (strncmp(rank, "full", 4) == 0)
        result.rank = EpetraExt::ModelEvaluator::DERIV_RANK_FULL;
    if (strncmp(rank, "deficient", 9) == 0)
        result.rank = EpetraExt::ModelEvaluator::DERIV_RANK_DEFICIENT;
    // supportsAdjoint attribute
    result.supportsAdjoint = getBoolObjectAttr(item, "supportsAdjoint");
    Py_DECREF(item);

    return result;
}
EpetraExt::ModelEvaluator::Derivative
getDerivativeItemObjectAttr(PyObject * object, CONST char * name, int i)
{
    // The Derivative python class object
    static
    PyObject * classDerivative = NULL;
    if (!classDerivative)
    {
        classDerivative = getClassFromModule(PyTrilinosEpetraExt, "Derivative");
        if (!classDerivative) throw PythonException();
    }
    // Get the item from the object attribute
    PyObject * tuple = getTupleObjectAttr(object, name);
    PyObject * item  = PyTuple_GetItem(tuple, i);
    Py_DECREF(tuple);
    if (!item) throw PythonException();
    if (!PyObject_IsInstance(item, classDerivative))
    {
        PyErr_Format(PyExc_TypeError, "Attribute '%s' is not tuple of Derivative", name);
        Py_DECREF(item);
        throw PythonException();
    }
    if (!objectAttrIsNone(item, "operator"))
    {
        // operator attribute
        Teuchos::RCP<Epetra_Operator> linearOp =
            getEpetraOperatorObjectAttr(item, "operator");
        Py_DECREF(item);
        return EpetraExt::ModelEvaluator::Derivative(linearOp);
    }
    if (!objectAttrIsNone(item, "derivativeMultiVector"))
    {
        // derivativeMultiVector attribute
        EpetraExt::ModelEvaluator::DerivativeMultiVector derivativeMultiVector =
            getDerivativeMultiVectorObjectAttr(item, "derivativeMultiVector");
        Py_DECREF(item);
        return EpetraExt::ModelEvaluator::Derivative(derivativeMultiVector);
    }
    Py_DECREF(item);

    return EpetraExt::ModelEvaluator::Derivative();
}
EpetraExt::ModelEvaluator::Evaluation<Epetra_Vector>
getEvaluationItemObjectAttr(PyObject * object, CONST char * name, int i)
{
    // The Evaluation python class object
    static
    PyObject * classEvaluation = NULL;
    if (!classEvaluation)
    {
        classEvaluation = getClassFromModule(PyTrilinosEpetraExt, "Evaluation");
        if (!classEvaluation) throw PythonException();
    }
    // Get the item from the object attribute
    PyObject * tuple = getTupleObjectAttr(object, name);
    PyObject * item  = PyTuple_GetItem(tuple, i);
    Py_DECREF(tuple);
    if (!item) throw PythonException();
    if (!PyObject_IsInstance(item, classEvaluation))
    {
        PyErr_Format(PyExc_TypeError, "Attribute '%s' is not tuple of Evaluation", name);
        Py_DECREF(item);
        throw PythonException();
    }
    // vector attribute
    Teuchos::RCP<Epetra_Vector> vector = getEpetraVectorObjectAttr(item, "vector");
    // type attribute
    EpetraExt::ModelEvaluator::EEvalType type;
    CONST char * typeStr = getStringObjectAttr(item, "type");
    if (strncmp(typeStr, "exact", 5) == 0)
        type = EpetraExt::ModelEvaluator::EVAL_TYPE_EXACT;
    if (strncmp(typeStr, "approx_deriv", 12) == 0)
        type = EpetraExt::ModelEvaluator::EVAL_TYPE_APPROX_DERIV;
    if (strncmp(typeStr, "very_approx_deriv", 17) == 0)
        type = EpetraExt::ModelEvaluator::EVAL_TYPE_VERY_APPROX_DERIV;
    Py_DECREF(item);
    return EpetraExt::ModelEvaluator::Evaluation<Epetra_Vector>(vector, type);
}