/** * \ingroup python_interface_edgeseq * \brief Copies an edge sequence object * \return the copied PyObject */ igraphmodule_EdgeSeqObject* igraphmodule_EdgeSeq_copy(igraphmodule_EdgeSeqObject* o) { igraphmodule_EdgeSeqObject *copy; copy=(igraphmodule_EdgeSeqObject*)PyType_GenericNew(Py_TYPE(o), 0, 0); if (copy == NULL) return NULL; if (igraph_es_type(&o->es) == IGRAPH_ES_VECTOR) { igraph_vector_t v; if (igraph_vector_copy(&v, o->es.data.vecptr)) { igraphmodule_handle_igraph_error(); return 0; } if (igraph_es_vector_copy(©->es, &v)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); return 0; } igraph_vector_destroy(&v); } else { copy->es = o->es; } copy->gref = o->gref; if (o->gref) Py_INCREF(o->gref); RC_ALLOC("EdgeSeq(copy)", copy); return copy; }
/** * \ingroup python_interface_edgeseq * \brief Returns the item at the given index in the sequence */ PyObject* igraphmodule_EdgeSeq_sq_item(igraphmodule_EdgeSeqObject* self, Py_ssize_t i) { igraph_t *g; igraph_integer_t idx = -1; if (!self->gref) return NULL; g=&GET_GRAPH(self); switch (igraph_es_type(&self->es)) { case IGRAPH_ES_ALL: if (i >= 0 && i < igraph_ecount(g)) idx = (igraph_integer_t)i; break; case IGRAPH_ES_VECTOR: case IGRAPH_ES_VECTORPTR: if (i >= 0 && i < igraph_vector_size(self->es.data.vecptr)) idx = (igraph_integer_t)VECTOR(*self->es.data.vecptr)[i]; break; case IGRAPH_ES_1: if (i == 0) idx = self->es.data.eid; break; case IGRAPH_ES_SEQ: if (i >= 0 && i < self->es.data.seq.to - self->es.data.seq.from) idx = self->es.data.seq.from + (igraph_integer_t)i; break; /* TODO: IGRAPH_ES_PAIRS, IGRAPH_ES_ADJ, IGRAPH_ES_PATH, IGRAPH_ES_MULTIPATH - someday :) They are unused yet in the Python interface */ } if (idx < 0) { PyErr_SetString(PyExc_IndexError, "edge index out of range"); return NULL; } return igraphmodule_Edge_New(self->gref, idx); }
/** \ingroup python_interface_edgeseq * \brief Sets the list of values for a given attribute */ int igraphmodule_EdgeSeq_set_attribute_values_mapping(igraphmodule_EdgeSeqObject* self, PyObject* attrname, PyObject* values) { PyObject *dict, *list, *item; igraphmodule_GraphObject *gr; igraph_vector_t es; long i, j, n, no_of_edges; gr = self->gref; dict = ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_EDGE]; if (!igraphmodule_attribute_name_check(attrname)) return -1; if (values == 0) { if (igraph_es_type(&self->es) == IGRAPH_ES_ALL) return PyDict_DelItem(dict, attrname); PyErr_SetString(PyExc_TypeError, "can't delete attribute from an edge sequence not representing the whole graph"); return -1; } if (PyString_Check(values) || !PySequence_Check(values)) { /* If values is a string or not a sequence, we construct a list with a * single element (the value itself) and then call ourselves again */ int result; PyObject *newList = PyList_New(1); if (newList == 0) return -1; Py_INCREF(values); PyList_SET_ITEM(newList, 0, values); /* reference stolen here */ result = igraphmodule_EdgeSeq_set_attribute_values_mapping(self, attrname, newList); Py_DECREF(newList); return result; } n=PySequence_Size(values); if (n<0) return -1; if (igraph_es_type(&self->es) == IGRAPH_ES_ALL) { no_of_edges = (long)igraph_ecount(&gr->g); if (n == 0 && no_of_edges > 0) { PyErr_SetString(PyExc_ValueError, "sequence must not be empty"); return -1; } /* Check if we already have attributes with the given name */ list = PyDict_GetItem(dict, attrname); if (list != 0) { /* Yes, we have. Modify its items to the items found in values */ for (i=0, j=0; i<no_of_edges; i++, j++) { if (j == n) j = 0; item = PySequence_GetItem(values, j); if (item == 0) return -1; /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ if (PyList_SetItem(list, i, item)) { Py_DECREF(item); return -1; } /* PyList_SetItem stole a reference to the item automatically */ } } else if (values != 0) { /* We don't have attributes with the given name yet. Create an entry * in the dict, create a new list and copy everything */ list = PyList_New(no_of_edges); if (list == 0) return -1; for (i=0, j=0; i<no_of_edges; i++, j++) { if (j == n) j = 0; item = PySequence_GetItem(values, j); if (item == 0) { Py_DECREF(list); return -1; } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ PyList_SET_ITEM(list, i, item); /* PyList_SET_ITEM stole a reference to the item automatically */ } if (PyDict_SetItem(dict, attrname, list)) { Py_DECREF(list); return -1; } Py_DECREF(list); /* compensating for PyDict_SetItem */ } } else { /* We are working with a subset of the graph. Convert the sequence to a * vector and loop through it */ if (igraph_vector_init(&es, 0)) { igraphmodule_handle_igraph_error(); return -1; } if (igraph_es_as_vector(&gr->g, self->es, &es)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&es); return -1; } no_of_edges = (long)igraph_vector_size(&es); if (n == 0 && no_of_edges > 0) { PyErr_SetString(PyExc_ValueError, "sequence must not be empty"); igraph_vector_destroy(&es); return -1; } /* Check if we already have attributes with the given name */ list = PyDict_GetItem(dict, attrname); if (list != 0) { /* Yes, we have. Modify its items to the items found in values */ for (i=0, j=0; i<no_of_edges; i++, j++) { if (j == n) j = 0; item = PySequence_GetItem(values, j); if (item == 0) { igraph_vector_destroy(&es); return -1; } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ if (PyList_SetItem(list, (long)VECTOR(es)[i], item)) { Py_DECREF(item); igraph_vector_destroy(&es); return -1; } /* PyList_SetItem stole a reference to the item automatically */ } igraph_vector_destroy(&es); } else if (values != 0) { /* We don't have attributes with the given name yet. Create an entry * in the dict, create a new list, fill with None for vertices not in the * sequence and copy the rest */ long n2 = igraph_ecount(&gr->g); list = PyList_New(n2); if (list == 0) { igraph_vector_destroy(&es); return -1; } for (i=0; i<n2; i++) { Py_INCREF(Py_None); PyList_SET_ITEM(list, i, Py_None); } for (i=0, j=0; i<no_of_edges; i++, j++) { if (j == n) j = 0; item = PySequence_GetItem(values, j); if (item == 0) { igraph_vector_destroy(&es); Py_DECREF(list); return -1; } /* No need to Py_INCREF(item), PySequence_GetItem returns a new reference */ PyList_SET_ITEM(list, (long)VECTOR(es)[i], item); /* PyList_SET_ITEM stole a reference to the item automatically */ } igraph_vector_destroy(&es); if (PyDict_SetItem(dict, attrname, list)) { Py_DECREF(list); return -1; } Py_DECREF(list); /* compensating for PyDict_SetItem */ } } return 0; }
/** \ingroup python_interface_edgeseq * \brief Returns the list of values for a given attribute */ PyObject* igraphmodule_EdgeSeq_get_attribute_values(igraphmodule_EdgeSeqObject* self, PyObject* o) { igraphmodule_GraphObject *gr = self->gref; PyObject *result=0, *values, *item; long int i, n; if (!igraphmodule_attribute_name_check(o)) return 0; PyErr_Clear(); values=PyDict_GetItem(ATTR_STRUCT_DICT(&gr->g)[ATTRHASH_IDX_EDGE], o); if (!values) { PyErr_SetString(PyExc_KeyError, "Attribute does not exist"); return NULL; } else if (PyErr_Occurred()) return NULL; switch (igraph_es_type(&self->es)) { case IGRAPH_ES_NONE: n = 0; result = PyList_New(0); break; case IGRAPH_ES_ALL: n = PyList_Size(values); result = PyList_New(n); if (!result) return 0; for (i=0; i<n; i++) { item = PyList_GET_ITEM(values, i); Py_INCREF(item); PyList_SET_ITEM(result, i, item); } break; case IGRAPH_ES_VECTOR: case IGRAPH_ES_VECTORPTR: n = igraph_vector_size(self->es.data.vecptr); result = PyList_New(n); if (!result) return 0; for (i=0; i<n; i++) { item = PyList_GET_ITEM(values, (long)VECTOR(*self->es.data.vecptr)[i]); Py_INCREF(item); PyList_SET_ITEM(result, i, item); } break; case IGRAPH_ES_SEQ: n = self->es.data.seq.to - self->es.data.seq.from; result = PyList_New(n); if (!result) return 0; for (i=0; i<n; i++) { item = PyList_GET_ITEM(values, (long)self->es.data.seq.from+i); Py_INCREF(item); PyList_SET_ITEM(result, i, item); } break; default: PyErr_SetString(PyExc_RuntimeError, "invalid edge selector"); } return result; }
int EdgeSelector::type() const noexcept { return igraph_es_type(ptr()); }