/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2006 Gabor Csardi MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /************************ Miscellaneous functions *************************/ #include "graphobject.h" #include "convert.h" #include "error.h" #include "memory.h" /** * \ingroup python_interface_conversion * \brief Converts a Python integer list to an igraph \c igraph_vector_t * The incoming \c igraph_vector_t should be uninitialized. Raises suitable * Python exceptions when needed. * * \param list the Python list to be converted * \param v the \c igraph_vector_t containing the result * \param need_non_negative if true, checks whether all elements are non-negative * \param pairs if true, assumes that every list element is a pair of integers * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyList_to_vector_t(PyObject *list, igraph_vector_t *v, igraph_bool_t need_non_negative, igraph_bool_t pairs) { PyObject *item, *i1, *i2; int i, j, k, ok; long idx=0, idx2=0; if (!PyList_Check(list)) { ok=1; if (pairs) { // a pair was given instead of a list // Let's assume that the user meant a list consisting of this single pair if (PyTuple_Check(list) && PyTuple_Size(list)==2) { i1=i2=NULL; i1=PyTuple_GetItem(list, 0); if (i1) i2=PyTuple_GetItem(list, 1); if (i1 && i2) { if (PyInt_Check(i1) && PyInt_Check(i2)) { idx=PyInt_AsLong(i1); idx2=PyInt_AsLong(i2); // domain checking if (need_non_negative && (idx<0 || idx2<0)) ok=0; } else ok=0; } else { // should not ever get here // Exception was set by PyTuple_GetItem, so return immediately return 1; } } else { PyErr_SetString(PyExc_TypeError, "List of pairs or a single pair of integer expected"); return 1; } if (ok) { igraph_vector_init(v, 2); VECTOR(*v)[0]=(igraph_real_t)idx; VECTOR(*v)[1]=(igraph_real_t)idx2; } else { if (need_non_negative) PyErr_SetString(PyExc_TypeError, "List elements must be non-negative integers"); else PyErr_SetString(PyExc_TypeError, "List elements must be integers"); return 1; } } else if (PyInt_Check(list)) { // a single integer was given instead of a list // Let's assume that the user meant a list consisting of this single item igraph_vector_init(v, 1); VECTOR(*v)[0]=(igraph_real_t)PyInt_AsLong(list); } else { PyErr_SetString(PyExc_TypeError, "List or single integer expected"); return 1; } } else { // we received a list, so loop through all elements and add them // to a vector. // Non-integer or negative elements raise an exception j=PyList_Size(list); if (pairs) igraph_vector_init(v, 2*j); else igraph_vector_init(v, j); for (i=0, k=0; i>=1; list=PyList_New(n); /* populate the list with data */ for (i=0, j=0; inc) nc=n; } igraph_matrix_init(m, nr, nc); for (i=0; ig); Py_DECREF(t); } return 0; } /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a vertex selector * * \param o the Python object * \param vs the \c igraph_vs_t which will contain the result * \param return_single will be 1 if the selector selected only a single vertex, * 0 otherwise * \return 0 if everything was OK, 1 otherwise */ int igraphmodule_PyObject_to_vs_t(PyObject *o, igraph_vs_t *vs, igraph_bool_t *return_single) { *return_single=0; if (o==NULL || o == Py_None) { /* Returns a vertex sequence for all vertices */ igraph_vs_all(vs); } else if (PyInt_Check(o)) { /* Returns a vertex sequence for a single vertex ID */ igraph_vs_1(vs, PyInt_AsLong(o)); *return_single=1; } else if (PyLong_Check(o)) { /* Returns a vertex sequence for a single vertex ID */ igraph_vs_1(vs, PyLong_AsLong(o)); *return_single=1; } else { /* Returns a vertex sequence with the IDs returned by the iterator */ PyObject *iterator = PyObject_GetIter(o); PyObject *item; igraph_vector_t vector; if (iterator == NULL) { PyErr_SetString(PyExc_TypeError, "integer, long, iterable or None expected"); return 1; } IGRAPH_CHECK(igraph_vector_init(&vector, 0)); IGRAPH_FINALLY(igraph_vector_destroy, &vector); IGRAPH_CHECK(igraph_vector_reserve(&vector, 20)); while ((item = PyIter_Next(iterator))) { long val=-1; if (PyInt_Check(item)) val=PyInt_AsLong(item); else if (PyLong_Check(item)) val=PyLong_AsLong(item); Py_DECREF(item); if (val >= 0) igraph_vector_push_back(&vector, val); else { PyErr_SetString(PyExc_TypeError, "integer or long expected"); } if (PyErr_Occurred()) break; } Py_DECREF(iterator); if (PyErr_Occurred()) { igraph_vector_destroy(&vector); IGRAPH_FINALLY_CLEAN(1); return 1; } else { igraph_vs_vector_copy(vs, &vector); igraph_vector_destroy(&vector); IGRAPH_FINALLY_CLEAN(1); } } return 0; } /** * \ingroup python_interface_conversion * \brief Tries to interpret a Python object as a numeric attribute value list * * \param o the Python object * \param v the \c igraph_vector_t which will contain the result * \param g a \c igraphmodule_GraphObject object or \c NULL - used when the * provided Python object is not a list and we're trying to interpret it as * an attribute name. * \param type the attribute type (graph = 0, vertex = 1, edge = 2) to be used * \param def default value if the attribute name supplied is \c None * if \c o is not a list. * \return 0 if everything was OK, 1 otherwise * * If the Python object is not a list, tries to interpret it as an attribute * name. */ int igraphmodule_PyObject_to_attribute_values(PyObject *o, igraph_vector_t *v, igraphmodule_GraphObject* g, int type, igraph_real_t def) { PyObject* list = o; long i, n; if (o==NULL) return 1; if (o == Py_None) { if (type == ATTRHASH_IDX_VERTEX) n=igraph_vcount(&g->g); else if (type == ATTRHASH_IDX_EDGE) n=igraph_ecount(&g->g); else n=1; if (igraph_vector_init(v, n)) return 1; for (i=0; ig.attr)[type], o); if (!list) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_KeyError, "Attribute does not exist"); return 1; } } n=PyList_Size(list); if (igraph_vector_init(v, n)) return 1; for (i=0; i