// decodeType translates a Python object to a Go value. Its type must be // non-zero. func decodeType(pyType C.int, pyValue *C.PyObject) (value interface{}, err error) { switch pyType { case 0: err = getError() case 1: // nil case 2: value = false case 3: value = true case 4: value = C.GoString(C.PyString_AsString(pyValue)) case 5: value = int(C.PyInt_AsLong(pyValue)) case 6: var overflow C.int i := int64(C.PyLong_AsLongLongAndOverflow(pyValue, &overflow)) switch overflow { case -1: err = fmt.Errorf("Python integer %s is too small", stringify(pyValue)) case 0: value = i case 1: n := uint64(C.PyLong_AsUnsignedLongLong(pyValue)) if n == 0xffffffffffffffff { C.PyErr_Clear() err = fmt.Errorf("Python integer %s is too large", stringify(pyValue)) } else { value = n } } case 7: value = float64(C.PyFloat_AsDouble(pyValue)) case 8: value = complex(C.PyComplex_RealAsDouble(pyValue), C.PyComplex_ImagAsDouble(pyValue)) case 9: return decodeSequence(pyValue) case 10: return decodeMapping(pyValue) default: err = fmt.Errorf("unable to translate %s from Python", stringify(C.PyObject_Type(pyValue))) return } return }
func stringify(pyObject *C.PyObject) (s string) { if pyResult := C.PyObject_Str(pyObject); pyResult != nil { defer C.DECREF(pyResult) if cString := C.PyString_AsString(pyResult); cString != nil { s = C.GoString(cString) } } C.PyErr_Clear() return }
// getError translates the current Python exception to a Go error, and clears // the Python exception state. func getError() error { var ( pyType *C.PyObject pyValue *C.PyObject pyTrace *C.PyObject ) C.PyErr_Fetch(&pyType, &pyValue, &pyTrace) defer C.DECREF(pyType) defer C.DECREF(pyValue) defer xDECREF(pyTrace) C.PyErr_Clear() return fmt.Errorf("Python: %s", stringify(pyValue)) }
// void PyErr_Clear() // Clear the error indicator. If the error indicator is not set, there is no effect. func PyErr_Clear() { C.PyErr_Clear() }