Skip to content
Snippets Groups Projects
Commit c397ef1f authored by Kelvin Rodriguez's avatar Kelvin Rodriguez
Browse files

load now throw exceptions with python tracebacks

parent b641aa5c
No related branches found
No related tags found
No related merge requests found
......@@ -262,30 +262,37 @@ namespace ale {
str = PyBytes_AS_STRING(PyUnicode_AsUTF8String(pystr));
error_description = strdup(str);
/* See if we can get a full traceback */
// See if we can get a full traceback
module_name = PyUnicode_FromString("traceback");
pyth_module = PyImport_Import(module_name);
Py_DECREF(module_name);
if (pyth_module == NULL) {
return "Pyth_Module Empty";
throw runtime_error("getPyTraceback - Failed to import Python traceback Library");
}
pyth_func = PyObject_GetAttrString(pyth_module, "format_exception");
if (pyth_func && PyCallable_Check(pyth_func)) {
PyObject *pyth_val;
pyth_val = PyObject_CallFunctionObjArgs(pyth_func, ptype, pvalue, ptraceback, NULL);
pystr = PyObject_Str(pyth_val);
str = PyBytes_AS_STRING(PyUnicode_AsUTF8String(pystr));
full_backtrace = strdup(str);
Py_DECREF(pyth_val);
return std::string(full_backtrace);
}
return "End of if statement";
std::string join_cmd = "trace = ''.join(list(" + std::string(full_backtrace) + "))";
PyRun_SimpleString(join_cmd.c_str());
PyObject *evalModule = PyImport_AddModule( (char*)"__main__" );
PyObject *evalDict = PyModule_GetDict( evalModule );
PyObject *evalVal = PyDict_GetItemString( evalDict, "trace" );
full_backtrace = PyBytes_AS_STRING(PyUnicode_AsUTF8String(evalVal));
return std::string(error_description) + "\n" + std::string(full_backtrace);
}
return "No Pyerror";
// no traceback to return
return "";
}
std::string load(std::string filename) {
......@@ -300,9 +307,7 @@ namespace ale {
// Import the file as a Python module.
PyObject *pModule = PyImport_Import(PyUnicode_FromString("ale"));
if(!pModule) {
std::cout << "Error in import module " << std::endl;
throw getPyTraceback();
throw runtime_error(getPyTraceback());
}
// Create a dictionary for the contents of the module.
PyObject *pDict = PyModule_GetDict(pModule);
......@@ -310,15 +315,17 @@ namespace ale {
// Get the add method from the dictionary.
PyObject *pFunc = PyDict_GetItemString(pDict, "loads");
if(!pFunc) {
std::cout << "Error in getting func " << std::endl;
return getPyTraceback();
// import errors do not set a PyError flag, need to use a custom
// error message instead.
throw runtime_error("Failed to import ale.loads function from Python."
"This Usually indicates an error in the Ale Python Library."
"Check if Installed correctly and the function ale.loads exists.");
}
// Create a Python tuple to hold the arguments to the method.
PyObject *pArgs = PyTuple_New(1);
if(!pArgs) {
std::cout << "Error in creating args " << std::endl;
return getPyTraceback();
throw runtime_error(getPyTraceback());
}
// Set the Python int as the first and second arguments to the method.
......@@ -328,21 +335,23 @@ namespace ale {
// Call the function with the arguments.
PyObject* pResult = PyObject_CallObject(pFunc, pArgs);
if(!pResult) {
std::cout << "Error in call " << std::endl;
return getPyTraceback();
throw invalid_argument(getPyTraceback());
}
std::string cResult;
PyObject *temp_bytes = PyUnicode_AsUTF8String(pResult); // Owned reference
if (temp_bytes != NULL) {
// use PyObject_Str to ensure return is always a string
PyObject *pResultStr = PyObject_Str(pResult);
PyObject *temp_bytes = PyUnicode_AsUTF8String(pResultStr); // Owned reference
if(!temp_bytes){
throw invalid_argument(getPyTraceback());
}
char *temp_str = PyBytes_AS_STRING(temp_bytes); // Borrowed pointer
cResult = temp_str; // copy into std::string
Py_DECREF(temp_str);
} else {
return getPyTraceback();
}
Py_DECREF(pResultStr);
Py_DECREF(temp_bytes);
Py_DECREF(pArgs);
Py_DECREF(pModule);
......
......@@ -251,101 +251,9 @@ TEST(LinearInterpTest, GetRotationDifferentCounts) {
vector<double> times = {0, 1, 2};
vector<vector<double>> rots({{1,1,1,1}, {0,0,0,0}, {1,1,1,1}, {0,0,0,0}});
EXPECT_THROW(ale::getRotation(rots, times, 2, ale::linear), invalid_argument);
}
TEST(PyInterfaceTest, PyErrors) {
std::string test_lro_label =
"PDS_VERSION_ID = PDS3\n"
"\n"
"/*FILE CHARACTERISTICS*/\n"
"RECORD_TYPE = FIXED_LENGTH\n"
"RECORD_BYTES = 5064\n"
"FILE_RECORDS = 13313\n"
"LABEL_RECORDS = 1\n"
"^IMAGE = 2\n"
"\n"
"/*DATA IDENTIFICATION*/\n"
"DATA_SET_ID = \"LRO-L-LROC-2-EDR-V1.0\"\n"
"ORIGINAL_PRODUCT_ID = nacl0002fc60\n"
"PRODUCT_ID = M128963531LE\n"
"MISSION_NAME = \"LUNAR RECONNAISSANCE ORBITER\"\n"
"MISSION_PHASE_NAME = \"NOMINAL MISSION\"\n"
"INSTRUMENT_HOST_NAME = \"LUNAR RECONNAISSANCE ORBITER\"\n"
"INSTRUMENT_HOST_ID = LRO\n"
"INSTRUMENT_NAME = \"LUNAR RECONNAISSANCE ORBITER CAMERA\"\n"
"INSTRUMENT_ID = LROC\n"
"LRO:PREROLL_TIME = 2010-05-20T02:57:44.373\n"
"START_TIME = 2010-05-20T02:57:44.720\n"
"STOP_TIME = 2010-05-20T02:57:49.235\n"
"LRO:SPACECRAFT_CLOCK_PREROLL_COUNT = \"1/296017064:22937\"\n"
"SPACECRAFT_CLOCK_START_COUNT = \"1/296017064:45694\"\n"
"SPACECRAFT_CLOCK_STOP_COUNT = \"1/296017069:13866\"\n"
"ORBIT_NUMBER = 4138\n"
"PRODUCER_ID = LRO_LROC_TEAM\n"
"PRODUCT_CREATION_TIME = 2013-09-16T19:57:12\n"
"PRODUCER_INSTITUTION_NAME = \"ARIZONA STATE UNIVERSITY\"\n"
"PRODUCT_TYPE = EDR\n"
"PRODUCT_VERSION_ID = \"v1.8\"\n"
"UPLOAD_ID = \"SC_2010140_0000_A_V01.txt\"\n"
"\n"
"/*DATA DESCRIPTION*/\n"
"TARGET_NAME = \"MOON\"\n"
"RATIONALE_DESC = \"TARGET OF OPPORTUNITY\"\n"
"FRAME_ID = LEFT\n"
"DATA_QUALITY_ID = \"0\"\n"
"DATA_QUALITY_DESC = \"The DATA_QUALITY_ID is set to an 8-bit\n"
" value that encodes the following data quality information for the\n"
" observation. For each bit a value of 0 means FALSE and a value of 1 means\n"
" TRUE. More information about the data quality ID can be found in the LROC\n"
" EDR/CDR SIS, section 3.3 'Label and Header Descriptions'.\n"
" Bit 1: Temperature of focal plane array is out of bounds.\n"
" Bit 2: Threshold for saturated pixels is reached.\n"
" Bit 3: Threshold for under-saturated pixels is reached.\n"
" Bit 4: Observation is missing telemetry packets.\n"
" Bit 5: SPICE information is bad or missing.\n"
" Bit 6: Observation or housekeeping information is bad or missing.\n"
" Bit 7: Spare.\n"
" Bit 8: Spare.\"\n"
"\n"
"/*ENVIRONMENT*/\n"
"LRO:TEMPERATURE_SCS = 4.51 <degC>\n"
"LRO:TEMPERATURE_FPA = 17.88 <degC>\n"
"LRO:TEMPERATURE_FPGA = -12.33 <degC>\n"
"LRO:TEMPERATURE_TELESCOPE = 5.91 <degC>\n"
"LRO:TEMPERATURE_SCS_RAW = 2740\n"
"LRO:TEMPERATURE_FPA_RAW = 2107\n"
"LRO:TEMPERATURE_FPGA_RAW = 3418\n"
"LRO:TEMPERATURE_TELESCOPE_RAW = 2675\n"
"\n"
"/*IMAGING PARAMETERS*/\n"
"CROSSTRACK_SUMMING = 1\n"
"BANDWIDTH = 300 <nm>\n"
"CENTER_FILTER_WAVELENGTH = 600 <nm>\n"
"LINE_EXPOSURE_DURATION = 0.337600 <ms>\n"
"LRO:LINE_EXPOSURE_CODE = 0\n"
"LRO:DAC_RESET_LEVEL = 198\n"
"LRO:CHANNEL_A_OFFSET = 60\n"
"LRO:CHANNEL_B_OFFSET = 123\n"
"LRO:COMPAND_CODE = 3\n"
"LRO:LINE_CODE = 13\n"
"LRO:BTERM = (0,16,69,103,128)\n"
"LRO:MTERM = (0.5,0.25,0.125,0.0625,0.03125)\n"
"LRO:XTERM = (0,64,424,536,800)\n"
"LRO:COMPRESSION_FLAG = 1\n"
"LRO:MODE = 7\n"
"\n"
"/*DATA OBJECT*/\n"
"OBJECT = IMAGE\n"
" LINES = 13312\n"
" LINE_SAMPLES = 5064\n"
" SAMPLE_BITS = 8\n"
" SAMPLE_TYPE = LSB_INTEGER\n"
" UNIT = \"RAW_INSTRUMENT_COUNT\"\n"
" MD5_CHECKSUM = \"0fe91f4b2e93083ee0093e7c8d05f3bc\"\n"
"END_OBJECT = IMAGE\n"
"END\n";
std::string s = ale::load(test_lro_label);
std::cout << s << std::endl;
EXPECT_DOUBLE_EQ(1, 0);
TEST(PyInterfaceTest, LoadInvalidLabel) {
std::string label = "Not a Real Label";
EXPECT_THROW(ale::load(label), invalid_argument);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment