void Object_beginTypeContext()

in amplify/backend/function/iamxawswrangler/lib/python/pandas/_libs/src/ujson/python/objToJSON.c [1394:1892]


void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {
    PyObject *obj, *exc, *toDictFunc, *tmpObj, *values;
    TypeContext *pc;
    PyObjectEncoder *enc;
    double val;
    npy_int64 value;
    int unit;

    tc->prv = NULL;

    if (!_obj) {
        tc->type = JT_INVALID;
        return;
    }

    obj = (PyObject *)_obj;
    enc = (PyObjectEncoder *)tc->encoder;

    if (PyBool_Check(obj)) {
        tc->type = (obj == Py_True) ? JT_TRUE : JT_FALSE;
        return;
    } else if (obj == Py_None) {
        tc->type = JT_NULL;
        return;
    }

    pc = createTypeContext();
    if (!pc) {
        tc->type = JT_INVALID;
        return;
    }
    tc->prv = pc;

    if (PyTypeNum_ISDATETIME(enc->npyType)) {
        int64_t longVal;
        PyArray_VectorUnaryFunc *castfunc =
            PyArray_GetCastFunc(PyArray_DescrFromType(enc->npyType), NPY_INT64);
        if (!castfunc) {
            PyErr_Format(PyExc_ValueError, "Cannot cast numpy dtype %d to long",
                         enc->npyType);
        }
        castfunc(enc->npyValue, &longVal, 1, NULL, NULL);
        if (longVal == get_nat()) {
            tc->type = JT_NULL;
        } else {
            if (enc->datetimeIso) {
                if (enc->npyType == NPY_TIMEDELTA) {
                    pc->PyTypeToUTF8 = NpyTimeDeltaToIsoCallback;
                } else {
                    pc->PyTypeToUTF8 = NpyDateTimeToIsoCallback;
                }
                // Currently no way to pass longVal to iso function, so use
                // state management
                GET_TC(tc)->longValue = longVal;
                tc->type = JT_UTF8;
            } else {
                NPY_DATETIMEUNIT base =
                    ((PyObjectEncoder *)tc->encoder)->datetimeUnit;
                GET_TC(tc)->longValue = NpyDateTimeToEpoch(longVal, base);
                tc->type = JT_LONG;
            }
        }

        // TODO(username): this prevents infinite loop with
        // mixed-type DataFrames;
        // refactor
        enc->npyCtxtPassthru = NULL;
        enc->npyType = -1;
        return;
    }

    if (PyIter_Check(obj) ||
        (PyArray_Check(obj) && !PyArray_CheckScalar(obj))) {
        goto ISITERABLE;
    }

    if (PyLong_Check(obj)) {
        tc->type = JT_LONG;
        int overflow = 0;
        GET_TC(tc)->longValue = PyLong_AsLongLongAndOverflow(obj, &overflow);
        int err;
        err = (GET_TC(tc)->longValue == -1) && PyErr_Occurred();

        if (overflow) {
            tc->type = JT_BIGNUM;
        } else if (err) {
            goto INVALID;
        }

        return;
    } else if (PyFloat_Check(obj)) {
        val = PyFloat_AS_DOUBLE(obj);
        if (npy_isnan(val) || npy_isinf(val)) {
            tc->type = JT_NULL;
        } else {
            GET_TC(tc)->doubleValue = val;
            tc->type = JT_DOUBLE;
        }
        return;
    } else if (PyBytes_Check(obj)) {
        pc->PyTypeToUTF8 = PyBytesToUTF8;
        tc->type = JT_UTF8;
        return;
    } else if (PyUnicode_Check(obj)) {
        pc->PyTypeToUTF8 = PyUnicodeToUTF8;
        tc->type = JT_UTF8;
        return;
    } else if (PyObject_TypeCheck(obj, type_decimal)) {
        GET_TC(tc)->doubleValue = PyFloat_AsDouble(obj);
        tc->type = JT_DOUBLE;
        return;
    } else if (PyDateTime_Check(obj) || PyDate_Check(obj)) {
        if (PyObject_TypeCheck(obj, cls_nat)) {
            tc->type = JT_NULL;
            return;
        }

        if (enc->datetimeIso) {
            pc->PyTypeToUTF8 = PyDateTimeToIsoCallback;
            tc->type = JT_UTF8;
        } else {
            NPY_DATETIMEUNIT base =
                ((PyObjectEncoder *)tc->encoder)->datetimeUnit;
            GET_TC(tc)->longValue = PyDateTimeToEpoch(obj, base);
            tc->type = JT_LONG;
        }
        return;
    } else if (PyTime_Check(obj)) {
        pc->PyTypeToUTF8 = PyTimeToJSON;
        tc->type = JT_UTF8;
        return;
    } else if (PyArray_IsScalar(obj, Datetime)) {
        if (((PyDatetimeScalarObject *)obj)->obval == get_nat()) {
            tc->type = JT_NULL;
            return;
        }

        if (enc->datetimeIso) {
            pc->PyTypeToUTF8 = PyDateTimeToIsoCallback;
            tc->type = JT_UTF8;
        } else {
            NPY_DATETIMEUNIT base =
                ((PyObjectEncoder *)tc->encoder)->datetimeUnit;
            GET_TC(tc)->longValue = PyDateTimeToEpoch(obj, base);
            tc->type = JT_LONG;
        }
        return;
    } else if (PyDelta_Check(obj)) {
        if (PyObject_HasAttrString(obj, "value")) {
            value = get_long_attr(obj, "value");
        } else {
            value = total_seconds(obj) * 1000000000LL;  // nanoseconds per sec
        }

        if (value == get_nat()) {
            tc->type = JT_NULL;
            return;
        } else if (enc->datetimeIso) {
            pc->PyTypeToUTF8 = NpyTimeDeltaToIsoCallback;
            tc->type = JT_UTF8;
        } else {
            unit = ((PyObjectEncoder *)tc->encoder)->datetimeUnit;
            if (scaleNanosecToUnit(&value, unit) != 0) {
                // TODO(username): Add some kind of error handling here
            }

            exc = PyErr_Occurred();

            if (exc && PyErr_ExceptionMatches(PyExc_OverflowError)) {
                goto INVALID;
            }

            tc->type = JT_LONG;
        }
        GET_TC(tc)->longValue = value;
        return;
    } else if (PyArray_IsScalar(obj, Integer)) {
        tc->type = JT_LONG;
        PyArray_CastScalarToCtype(obj, &(GET_TC(tc)->longValue),
                                  PyArray_DescrFromType(NPY_INT64));

        exc = PyErr_Occurred();

        if (exc && PyErr_ExceptionMatches(PyExc_OverflowError)) {
            goto INVALID;
        }

        return;
    } else if (PyArray_IsScalar(obj, Bool)) {
        PyArray_CastScalarToCtype(obj, &(GET_TC(tc)->longValue),
                                  PyArray_DescrFromType(NPY_BOOL));
        tc->type = (GET_TC(tc)->longValue) ? JT_TRUE : JT_FALSE;
        return;
    } else if (PyArray_IsScalar(obj, Float) || PyArray_IsScalar(obj, Double)) {
        PyArray_CastScalarToCtype(obj, &(GET_TC(tc)->doubleValue),
                                  PyArray_DescrFromType(NPY_DOUBLE));
        tc->type = JT_DOUBLE;
        return;
    } else if (PyArray_Check(obj) && PyArray_CheckScalar(obj)) {
        PyErr_Format(PyExc_TypeError,
                     "%R (0d array) is not JSON serializable at the moment",
                     obj);
        goto INVALID;
    } else if (PyObject_TypeCheck(obj, cls_na)) {
        tc->type = JT_NULL;
        return;
    }

ISITERABLE:

    if (PyObject_TypeCheck(obj, cls_index)) {
        if (enc->outputFormat == SPLIT) {
            tc->type = JT_OBJECT;
            pc->iterBegin = Index_iterBegin;
            pc->iterEnd = Index_iterEnd;
            pc->iterNext = Index_iterNext;
            pc->iterGetValue = Index_iterGetValue;
            pc->iterGetName = Index_iterGetName;
            return;
        }

        pc->newObj = get_values(obj);
        if (pc->newObj) {
            tc->type = JT_ARRAY;
            pc->iterBegin = NpyArr_iterBegin;
            pc->iterEnd = NpyArr_iterEnd;
            pc->iterNext = NpyArr_iterNext;
            pc->iterGetValue = NpyArr_iterGetValue;
            pc->iterGetName = NpyArr_iterGetName;
        } else {
            goto INVALID;
        }

        return;
    } else if (PyObject_TypeCheck(obj, cls_series)) {
        if (enc->outputFormat == SPLIT) {
            tc->type = JT_OBJECT;
            pc->iterBegin = Series_iterBegin;
            pc->iterEnd = Series_iterEnd;
            pc->iterNext = Series_iterNext;
            pc->iterGetValue = Series_iterGetValue;
            pc->iterGetName = Series_iterGetName;
            return;
        }

        pc->newObj = get_values(obj);
        if (!pc->newObj) {
            goto INVALID;
        }

        if (enc->outputFormat == INDEX || enc->outputFormat == COLUMNS) {
            tc->type = JT_OBJECT;
            tmpObj = PyObject_GetAttrString(obj, "index");
            if (!tmpObj) {
                goto INVALID;
            }
            values = get_values(tmpObj);
            Py_DECREF(tmpObj);
            if (!values) {
                goto INVALID;
            }
            pc->columnLabelsLen = PyArray_DIM(pc->newObj, 0);
            pc->columnLabels = NpyArr_encodeLabels((PyArrayObject *)values, enc,
                                                   pc->columnLabelsLen);
            if (!pc->columnLabels) {
                goto INVALID;
            }
        } else {
            tc->type = JT_ARRAY;
        }
        pc->iterBegin = NpyArr_iterBegin;
        pc->iterEnd = NpyArr_iterEnd;
        pc->iterNext = NpyArr_iterNext;
        pc->iterGetValue = NpyArr_iterGetValue;
        pc->iterGetName = NpyArr_iterGetName;
        return;
    } else if (PyArray_Check(obj)) {
        if (enc->npyCtxtPassthru) {
            pc->npyarr = enc->npyCtxtPassthru;
            tc->type = (pc->npyarr->columnLabels ? JT_OBJECT : JT_ARRAY);

            pc->iterBegin = NpyArrPassThru_iterBegin;
            pc->iterNext = NpyArr_iterNext;
            pc->iterEnd = NpyArrPassThru_iterEnd;
            pc->iterGetValue = NpyArr_iterGetValue;
            pc->iterGetName = NpyArr_iterGetName;

            enc->npyCtxtPassthru = NULL;
            return;
        }

        tc->type = JT_ARRAY;
        pc->iterBegin = NpyArr_iterBegin;
        pc->iterEnd = NpyArr_iterEnd;
        pc->iterNext = NpyArr_iterNext;
        pc->iterGetValue = NpyArr_iterGetValue;
        pc->iterGetName = NpyArr_iterGetName;
        return;
    } else if (PyObject_TypeCheck(obj, cls_dataframe)) {
        if (enc->blkCtxtPassthru) {
            pc->pdblock = enc->blkCtxtPassthru;
            tc->type =
                (pc->pdblock->npyCtxts[0]->columnLabels ? JT_OBJECT : JT_ARRAY);

            pc->iterBegin = PdBlockPassThru_iterBegin;
            pc->iterEnd = PdBlockPassThru_iterEnd;
            pc->iterNext = PdBlock_iterNextItem;
            pc->iterGetName = PdBlock_iterGetName;
            pc->iterGetValue = NpyArr_iterGetValue;

            enc->blkCtxtPassthru = NULL;
            return;
        }

        if (enc->outputFormat == SPLIT) {
            tc->type = JT_OBJECT;
            pc->iterBegin = DataFrame_iterBegin;
            pc->iterEnd = DataFrame_iterEnd;
            pc->iterNext = DataFrame_iterNext;
            pc->iterGetValue = DataFrame_iterGetValue;
            pc->iterGetName = DataFrame_iterGetName;
            return;
        }

        if (is_simple_frame(obj)) {
            pc->iterBegin = NpyArr_iterBegin;
            pc->iterEnd = NpyArr_iterEnd;
            pc->iterNext = NpyArr_iterNext;
            pc->iterGetName = NpyArr_iterGetName;

            pc->newObj = PyObject_GetAttrString(obj, "values");
            if (!pc->newObj) {
                goto INVALID;
            }
        } else {
            pc->iterBegin = PdBlock_iterBegin;
            pc->iterEnd = PdBlock_iterEnd;
            pc->iterNext = PdBlock_iterNext;
            pc->iterGetName = PdBlock_iterGetName;
        }
        pc->iterGetValue = NpyArr_iterGetValue;

        if (enc->outputFormat == VALUES) {
            tc->type = JT_ARRAY;
        } else if (enc->outputFormat == RECORDS) {
            tc->type = JT_ARRAY;
            tmpObj = PyObject_GetAttrString(obj, "columns");
            if (!tmpObj) {
                goto INVALID;
            }
            values = get_values(tmpObj);
            if (!values) {
                Py_DECREF(tmpObj);
                goto INVALID;
            }
            pc->columnLabelsLen = PyObject_Size(tmpObj);
            pc->columnLabels = NpyArr_encodeLabels((PyArrayObject *)values, enc,
                                                   pc->columnLabelsLen);
            Py_DECREF(tmpObj);
            if (!pc->columnLabels) {
                goto INVALID;
            }
        } else if (enc->outputFormat == INDEX || enc->outputFormat == COLUMNS) {
            tc->type = JT_OBJECT;
            tmpObj = (enc->outputFormat == INDEX
                          ? PyObject_GetAttrString(obj, "index")
                          : PyObject_GetAttrString(obj, "columns"));
            if (!tmpObj) {
                goto INVALID;
            }
            values = get_values(tmpObj);
            if (!values) {
                Py_DECREF(tmpObj);
                goto INVALID;
            }
            pc->rowLabelsLen = PyObject_Size(tmpObj);
            pc->rowLabels = NpyArr_encodeLabels((PyArrayObject *)values, enc,
                                                pc->rowLabelsLen);
            Py_DECREF(tmpObj);
            tmpObj = (enc->outputFormat == INDEX
                          ? PyObject_GetAttrString(obj, "columns")
                          : PyObject_GetAttrString(obj, "index"));
            if (!tmpObj) {
                NpyArr_freeLabels(pc->rowLabels, pc->rowLabelsLen);
                pc->rowLabels = NULL;
                goto INVALID;
            }
            values = get_values(tmpObj);
            if (!values) {
                Py_DECREF(tmpObj);
                NpyArr_freeLabels(pc->rowLabels, pc->rowLabelsLen);
                pc->rowLabels = NULL;
                goto INVALID;
            }
            pc->columnLabelsLen = PyObject_Size(tmpObj);
            pc->columnLabels = NpyArr_encodeLabels((PyArrayObject *)values, enc,
                                                   pc->columnLabelsLen);
            Py_DECREF(tmpObj);
            if (!pc->columnLabels) {
                NpyArr_freeLabels(pc->rowLabels, pc->rowLabelsLen);
                pc->rowLabels = NULL;
                goto INVALID;
            }

            if (enc->outputFormat == COLUMNS) {
                pc->transpose = 1;
            }
        } else {
            goto INVALID;
        }
        return;
    } else if (PyDict_Check(obj)) {
        tc->type = JT_OBJECT;
        pc->iterBegin = Dict_iterBegin;
        pc->iterEnd = Dict_iterEnd;
        pc->iterNext = Dict_iterNext;
        pc->iterGetValue = Dict_iterGetValue;
        pc->iterGetName = Dict_iterGetName;
        pc->dictObj = obj;
        Py_INCREF(obj);

        return;
    } else if (PyList_Check(obj)) {
        tc->type = JT_ARRAY;
        pc->iterBegin = List_iterBegin;
        pc->iterEnd = List_iterEnd;
        pc->iterNext = List_iterNext;
        pc->iterGetValue = List_iterGetValue;
        pc->iterGetName = List_iterGetName;
        return;
    } else if (PyTuple_Check(obj)) {
        tc->type = JT_ARRAY;
        pc->iterBegin = Tuple_iterBegin;
        pc->iterEnd = Tuple_iterEnd;
        pc->iterNext = Tuple_iterNext;
        pc->iterGetValue = Tuple_iterGetValue;
        pc->iterGetName = Tuple_iterGetName;
        return;
    } else if (PyAnySet_Check(obj)) {
        tc->type = JT_ARRAY;
        pc->iterBegin = Set_iterBegin;
        pc->iterEnd = Set_iterEnd;
        pc->iterNext = Set_iterNext;
        pc->iterGetValue = Set_iterGetValue;
        pc->iterGetName = Set_iterGetName;
        return;
    }

    toDictFunc = PyObject_GetAttrString(obj, "toDict");

    if (toDictFunc) {
        PyObject *tuple = PyTuple_New(0);
        PyObject *toDictResult = PyObject_Call(toDictFunc, tuple, NULL);
        Py_DECREF(tuple);
        Py_DECREF(toDictFunc);

        if (toDictResult == NULL) {
            PyErr_Clear();
            tc->type = JT_NULL;
            return;
        }

        if (!PyDict_Check(toDictResult)) {
            Py_DECREF(toDictResult);
            tc->type = JT_NULL;
            return;
        }

        tc->type = JT_OBJECT;
        pc->iterBegin = Dict_iterBegin;
        pc->iterEnd = Dict_iterEnd;
        pc->iterNext = Dict_iterNext;
        pc->iterGetValue = Dict_iterGetValue;
        pc->iterGetName = Dict_iterGetName;
        pc->dictObj = toDictResult;
        return;
    }

    PyErr_Clear();

    if (enc->defaultHandler) {
        Object_invokeDefaultHandler(obj, enc);
        goto INVALID;
    }

    tc->type = JT_OBJECT;
    pc->iterBegin = Dir_iterBegin;
    pc->iterEnd = Dir_iterEnd;
    pc->iterNext = Dir_iterNext;
    pc->iterGetValue = Dir_iterGetValue;
    pc->iterGetName = Dir_iterGetName;
    return;

INVALID:
    tc->type = JT_INVALID;
    PyObject_Free(tc->prv);
    tc->prv = NULL;
    return;
}