static PyObj obj_new(PyTypeObject *subtype, PyObj args, PyObj kw) { static char *words[] = {"source", "mod", NULL}; PyObj src = NULL, mod = NULL, rob = NULL, typmodin_ob = NULL; Datum d; bool isnull = true; int32 typmod = -1; if (DB_IS_NOT_READY()) return(NULL); /* * The type *must* be a PyPgType instance. * Use CheckExact for speed. * Subclassing PyPgType_Type is not supported. */ if (PyPgObjectType_Require(subtype)) return(NULL); /* * Grab a single "source" argument and an * optional "mod" from the args and kw. */ if (!PyArg_ParseTupleAndKeywords(args, kw, "O|O", words, &src, &mod)) return(NULL); if (mod != NULL && mod != Py_None) { PyObj lo; if (!PyList_CheckExact(mod)) { lo = Py_Call((PyObj) &PyList_Type, mod); if (lo == NULL) { PyErr_SetString(PyExc_ValueError, "'mod' keyword must be a sequence"); return(NULL); } } else { Py_INCREF(mod); lo = mod; } typmodin_ob = Py_Call(PyPg_cstring_Array_Type, lo); Py_DECREF(lo); if (typmodin_ob == NULL) { PyErr_SetString(PyExc_ValueError, "invalid typmod object"); return(NULL); } } else if (Py_TYPE(src) == subtype) { /* * Exact type and no typmod. */ rob = src; Py_INCREF(rob); return(rob); } PG_TRY(); { if (typmodin_ob != NULL) { typmod = PyPgType_modin((PyObj) subtype, typmodin_ob); } if (src == Py_None) { d = 0; isnull = true; } else { PyPgType_DatumNew((PyObj) subtype, src, typmod, &d, &isnull); } if (isnull) { rob = Py_None; Py_INCREF(rob); } else { rob = PyPgObject_New(subtype, d); if (PyPgType_ShouldFree(subtype)) { Datum fd = d; d = 0; isnull = true; /* * If it fails to pfree, don't try it again in * the catch. */ pfree(DatumGetPointer(fd)); } } } PG_CATCH(); { Py_XDECREF(rob); rob = NULL; if (!isnull && PyPgType_ShouldFree(subtype)) pfree(DatumGetPointer(d)); PyErr_SetPgError(false); } PG_END_TRY(); Py_XDECREF(typmodin_ob); return(rob); }
/* * array_from_elements - classmethod to build an array */ static PyObj array_from_elements(PyObj self, PyObj args, PyObj kw) { static char *kwlist[] = {"elements", "dimensions", "lowerbounds", NULL}; PyObj rob = NULL, iter, listob, dims_ob = NULL, lbs_ob = NULL; int dims[MAXDIM]; int lbs[MAXDIM] = {1, 0,}; int ndims = 1, nelems; Py_ssize_t i; ArrayType *rat = NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, "O|OO:from_elements", kwlist, &iter, &dims_ob, &lbs_ob)) { return(NULL); } listob = Py_Call((PyObj) &PyList_Type, iter); if (listob == NULL) return(NULL); Assert(PyList_CheckExact(listob)); /* * Convert the dimensions keyword into a tuple and extract the values * into the dims[] array. */ if (dims_ob != NULL && dims_ob != Py_None) { PyObj tdims_ob; tdims_ob = Py_Call((PyObj) &PyTuple_Type, dims_ob); if (tdims_ob == NULL) goto fail; ndims = PyTuple_GET_SIZE(tdims_ob); if (ndims > MAXDIM) { Py_DECREF(tdims_ob); PyErr_Format(PyExc_ValueError, "too many dimensions (%d) for array", ndims); goto fail; } if (ndims > 0) { for (i = 0; i < ndims; ++i) { dims[i] = (int) PyNumber_AsSsize_t(PyTuple_GET_ITEM(tdims_ob, i), NULL); if (PyErr_Occurred()) { Py_DECREF(tdims_ob); goto fail; } } } else dims[0] = 0; Py_DECREF(tdims_ob); } else { dims[0] = PyList_GET_SIZE(listob); if (dims[0] == 0) ndims = 0; } nelems = dims[0]; if (ndims > 1) { for (i = 1; i < ndims; ++i) nelems = nelems * dims[i]; } if (nelems != PyList_GET_SIZE(listob)) { PyErr_Format(PyExc_ValueError, "dimension capacity (%d) does not accommodate the given elements (%d)", nelems, PyList_GET_SIZE(listob)); goto fail; } if (lbs_ob != NULL && lbs_ob != Py_None) { PyObj tlbs_ob; tlbs_ob = Py_Call((PyObj) &PyTuple_Type, lbs_ob); if (tlbs_ob == NULL) goto fail; if (PyTuple_GET_SIZE(tlbs_ob) > MAXDIM) { Py_DECREF(tlbs_ob); PyErr_SetString(PyExc_ValueError, "too many dimensions for array"); goto fail; } if (PyTuple_GET_SIZE(tlbs_ob) != ndims) { Py_DECREF(tlbs_ob); PyErr_Format(PyExc_ValueError, "number of lower bounds (%d) is " "inconsistent with dimensions (%d)", PyTuple_GET_SIZE(tlbs_ob), ndims); goto fail; } for (i = 0; i < PyTuple_GET_SIZE(tlbs_ob); ++i) { lbs[i] = (int) PyNumber_AsSsize_t(PyTuple_GET_ITEM(tlbs_ob, i), NULL); if (PyErr_Occurred()) { Py_DECREF(tlbs_ob); goto fail; } } Py_DECREF(tlbs_ob); } else { /* * No lower bounds specified, fill in with 1's. */ for (i = 0; i < ndims; ++i) { lbs[i] = 1; } } rat = array_from_list_and_info( PyPgType_GetElementType(self), listob, -1, ndims, dims, lbs); Py_DECREF(listob); if (rat != NULL) { rob = PyPgObject_New(self, PointerGetDatum(rat)); pfree(rat); } return(rob); fail: Py_XDECREF(listob); return(NULL); }
/* * Array.get_element(indexes) - Get an element from the array. * * This uses Python sequence semantics(zero-based indexes, IndexError's). */ static PyObj array_get_element(PyObj self, PyObj indexes_ob) { PyObj tup, element_type, rob = NULL; PyPgTypeInfo atypinfo, typinfo; ArrayType *at; int i, nindexes, indexes[MAXDIM] = {0,}; /* * Convert the indexes_ob into a tuple and extract the values * into the indexes[] array. Do any necessary checks along the way. */ tup = Py_Call((PyObj) &PyTuple_Type, indexes_ob); if (tup == NULL) return(NULL); nindexes = (int) PyTuple_GET_SIZE(tup); if (!(nindexes > 0)) { Py_DECREF(tup); PyErr_SetString(PyExc_ValueError, "empty index tuple"); return(NULL); } at = DatumGetArrayTypeP(PyPgObject_GetDatum(self)); Assert(at != NULL); if (nindexes != ARR_NDIM(at)) { Py_DECREF(tup); if (ARR_NDIM(at) == 0) PyErr_SetString(PyExc_IndexError, "no elements in array"); else PyErr_Format(PyExc_ValueError, "element access requires exactly %d indexes, given %d", ARR_NDIM(at), nindexes); return(NULL); } for (i = 0; i < nindexes; ++i) { int index; index = (int) PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, i), NULL); if (PyErr_Occurred()) { Py_DECREF(tup); return(NULL); } /* * Adjust for backwards based access. (feature of get_element) */ if (index < 0) indexes[i] = index + ARR_DIMS(at)[i]; else indexes[i] = index; if (indexes[i] >= ARR_DIMS(at)[i] || indexes[i] < 0) { PyErr_Format(PyExc_IndexError, "index %d out of range %d for axis %d", index, ARR_DIMS(at)[0], i); Py_DECREF(tup); return(NULL); } /* * Adjust by the lowerbounds.. */ indexes[i] = indexes[i] + ARR_LBOUND(at)[i]; } Py_DECREF(tup); atypinfo = PyPgTypeInfo(Py_TYPE(self)); element_type = PyPgType_GetElementType(Py_TYPE(self)); typinfo = PyPgTypeInfo(element_type); PG_TRY(); { Datum rd; bool isnull = false; rd = array_ref(at, nindexes, indexes, atypinfo->typlen, typinfo->typlen, typinfo->typbyval, typinfo->typalign, &isnull); if (isnull) { rob = Py_None; Py_INCREF(rob); } else { /* * It points into the array structure, so there's no need to free. */ rob = PyPgObject_New(element_type, rd); } } PG_CATCH(); { PyErr_SetPgError(false); } PG_END_TRY(); return(rob); }
static PyObj array_sql_get_element(PyObj self, PyObj indexes_ob) { PyObj tup, element_type, rob = NULL; PyPgTypeInfo atypinfo, typinfo; ArrayType *at; int i, nindexes, indexes[MAXDIM] = {0,}; /* * Convert the dimensions keyword into a tuple and extract the values * into the dims[] array. */ tup = Py_Call((PyObj) &PyTuple_Type, indexes_ob); if (tup == NULL) return(NULL); at = DatumGetArrayTypeP(PyPgObject_GetDatum(self)); Assert(at != NULL); nindexes = (int) PyTuple_GET_SIZE(tup); if (nindexes != ARR_NDIM(at)) { Py_DECREF(tup); Py_INCREF(Py_None); return(Py_None); } for (i = 0; i < nindexes; ++i) { indexes[i] = (int) PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, i), NULL); if (PyErr_Occurred()) { Py_DECREF(tup); return(NULL); } } Py_DECREF(tup); atypinfo = PyPgTypeInfo(Py_TYPE(self)); element_type = PyPgType_GetElementType(Py_TYPE(self)); typinfo = PyPgTypeInfo(element_type); /* * Single dimenion array? Get an element. */ PG_TRY(); { Datum rd; bool isnull = false; rd = array_ref(at, nindexes, indexes, atypinfo->typlen, typinfo->typlen, typinfo->typbyval, typinfo->typalign, &isnull); if (isnull) { rob = Py_None; Py_INCREF(rob); } else { /* * It points into the array structure, so there's no need to free. */ rob = PyPgObject_New(element_type, rd); } } PG_CATCH(); { PyErr_SetPgError(false); } PG_END_TRY(); return(rob); }