@@ -331,15 +331,19 @@ PyObject* igraphmodule_EdgeSeq_get_attribute_values_mapping(igraphmodule_EdgeSeq
331331 }
332332
333333 /* Handle strings according to the mapping protocol */
334- if (PyBaseString_Check (o ))
334+ if (PyBaseString_Check (o )) {
335335 return igraphmodule_EdgeSeq_get_attribute_values (self , o );
336+ }
336337
337338 /* Handle iterables and slices by calling the select() method */
338339 if (PySlice_Check (o ) || PyObject_HasAttrString (o , "__iter__" )) {
339340 PyObject * result , * args ;
340341 args = Py_BuildValue ("(O)" , o );
341- if (!args )
342+
343+ if (!args ) {
342344 return NULL ;
345+ }
346+
343347 result = igraphmodule_EdgeSeq_select (self , args );
344348 Py_DECREF (args );
345349 return result ;
@@ -559,23 +563,25 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject
559563 igraphmodule_EdgeSeqObject * result ;
560564 igraphmodule_GraphObject * gr ;
561565 igraph_integer_t igraph_idx ;
566+ igraph_bool_t working_on_whole_graph = igraph_es_is_all (& self -> es );
567+ igraph_vector_t v , v2 ;
562568 long i , j , n , m ;
563569
564- gr = self -> gref ;
565- result = igraphmodule_EdgeSeq_copy (self );
570+ gr = self -> gref ;
571+ result = igraphmodule_EdgeSeq_copy (self );
566572 if (result == 0 )
567573 return NULL ;
568574
569575 /* First, filter by positional arguments */
570576 n = PyTuple_Size (args );
571- for (i = 0 ; i < n ; i ++ ) {
577+ for (i = 0 ; i < n ; i ++ ) {
572578 PyObject * item = PyTuple_GET_ITEM (args , i );
573579 if (item == Py_None ) {
574580 /* None means: select nothing */
575581 igraph_es_destroy (& result -> es );
576582 igraph_es_none (& result -> es );
577583 /* We can simply bail out here */
578- return (PyObject * )result ;
584+ return (PyObject * ) result ;
579585 } else if (PyCallable_Check (item )) {
580586 /* Call the callable for every edge in the current sequence to
581587 * determine what's up */
@@ -588,7 +594,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject
588594 }
589595
590596 m = PySequence_Size ((PyObject * )result );
591- for (j = 0 ; j < m ; j ++ ) {
597+ for (j = 0 ; j < m ; j ++ ) {
592598 PyObject * edge = PySequence_GetItem ((PyObject * )result , j );
593599 PyObject * call_result ;
594600 if (edge == 0 ) {
@@ -602,10 +608,12 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject
602608 igraph_vector_destroy (& v );
603609 return NULL ;
604610 }
605- if (PyObject_IsTrue (call_result ))
611+ if (PyObject_IsTrue (call_result )) {
606612 igraph_vector_push_back (& v ,
607613 igraphmodule_Edge_get_index_long ((igraphmodule_EdgeObject * )edge ));
608- else was_excluded = 1 ;
614+ } else {
615+ was_excluded = 1 ;
616+ }
609617 Py_DECREF (call_result );
610618 Py_DECREF (edge );
611619 }
@@ -627,79 +635,105 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject
627635 * to restrict the edge set. Integers are interpreted as indices on the
628636 * edge set and NOT on the original, untouched edge sequence of the
629637 * graph */
630- igraph_vector_t v , v2 ;
631638 if (igraph_vector_init (& v , 0 )) {
632639 igraphmodule_handle_igraph_error ();
633640 return 0 ;
634641 }
635- if (igraph_vector_init (& v2 , 0 )) {
636- igraph_vector_destroy (& v );
637- igraphmodule_handle_igraph_error ();
638- return 0 ;
639- }
640- if (igraph_es_as_vector (& gr -> g , self -> es , & v2 )) {
641- igraph_vector_destroy (& v );
642- igraph_vector_destroy (& v2 );
643- igraphmodule_handle_igraph_error ();
644- return 0 ;
642+
643+ if (!working_on_whole_graph ) {
644+ /* Extract the current vertex sequence into a vector */
645+ if (igraph_vector_init (& v2 , 0 )) {
646+ igraph_vector_destroy (& v );
647+ igraphmodule_handle_igraph_error ();
648+ return 0 ;
649+ }
650+ if (igraph_es_as_vector (& gr -> g , self -> es , & v2 )) {
651+ igraph_vector_destroy (& v );
652+ igraph_vector_destroy (& v2 );
653+ igraphmodule_handle_igraph_error ();
654+ return 0 ;
655+ }
656+ m = igraph_vector_size (& v2 );
657+ } else {
658+ /* v2 left uninitialized, we are not going to use it as it would
659+ * simply contain integers from 0 to ecount(g)-1 */
660+ m = igraph_ecount (& gr -> g );
645661 }
646- m = igraph_vector_size ( & v2 );
647- for (; i < n ; i ++ ) {
662+
663+ for (; i < n ; i ++ ) {
648664 PyObject * item2 = PyTuple_GET_ITEM (args , i );
649665 long idx ;
650666 if (!PyLong_Check (item2 )) {
651667 Py_DECREF (result );
652668 PyErr_SetString (PyExc_TypeError , "edge indices expected" );
653669 igraph_vector_destroy (& v );
654- igraph_vector_destroy (& v2 );
670+ if (!working_on_whole_graph ) {
671+ igraph_vector_destroy (& v2 );
672+ }
655673 return NULL ;
656674 }
657675 idx = PyLong_AsLong (item2 );
658676 if (idx >= m || idx < 0 ) {
659677 PyErr_SetString (PyExc_ValueError , "edge index out of range" );
660678 igraph_vector_destroy (& v );
661- igraph_vector_destroy (& v2 );
679+ if (!working_on_whole_graph ) {
680+ igraph_vector_destroy (& v2 );
681+ }
662682 return NULL ;
663683 }
664- if (igraph_vector_push_back (& v , VECTOR (v2 )[idx ])) {
684+ if (igraph_vector_push_back (& v , working_on_whole_graph ? idx : VECTOR (v2 )[idx ])) {
665685 Py_DECREF (result );
666686 igraphmodule_handle_igraph_error ();
667687 igraph_vector_destroy (& v );
668- igraph_vector_destroy (& v2 );
688+ if (!working_on_whole_graph ) {
689+ igraph_vector_destroy (& v2 );
690+ }
669691 return NULL ;
670692 }
671693 }
672- igraph_vector_destroy (& v2 );
694+
695+ if (!working_on_whole_graph ) {
696+ igraph_vector_destroy (& v2 );
697+ }
698+
673699 igraph_es_destroy (& result -> es );
700+
674701 if (igraph_es_vector_copy (& result -> es , & v )) {
675702 Py_DECREF (result );
676703 igraphmodule_handle_igraph_error ();
677704 igraph_vector_destroy (& v );
678705 return NULL ;
679706 }
707+
680708 igraph_vector_destroy (& v );
681709 } else {
682710 /* Iterators and everything that was not handled directly */
683711 PyObject * iter , * item2 ;
684- igraph_vector_t v , v2 ;
685712
686713 /* Allocate stuff */
687714 if (igraph_vector_init (& v , 0 )) {
688715 igraphmodule_handle_igraph_error ();
689716 return 0 ;
690717 }
691- if (igraph_vector_init (& v2 , 0 )) {
692- igraph_vector_destroy (& v );
693- igraphmodule_handle_igraph_error ();
694- return 0 ;
695- }
696- if (igraph_es_as_vector (& gr -> g , self -> es , & v2 )) {
697- igraph_vector_destroy (& v );
698- igraph_vector_destroy (& v2 );
699- igraphmodule_handle_igraph_error ();
700- return 0 ;
718+ if (!working_on_whole_graph ) {
719+ /* Extract the current vertex sequence into a vector */
720+ if (igraph_vector_init (& v2 , 0 )) {
721+ igraph_vector_destroy (& v );
722+ igraphmodule_handle_igraph_error ();
723+ return 0 ;
724+ }
725+ if (igraph_es_as_vector (& gr -> g , self -> es , & v2 )) {
726+ igraph_vector_destroy (& v );
727+ igraph_vector_destroy (& v2 );
728+ igraphmodule_handle_igraph_error ();
729+ return 0 ;
730+ }
731+ m = igraph_vector_size (& v2 );
732+ } else {
733+ /* v2 left uninitialized, we are not going to use it as it would
734+ * simply contain integers from 0 to ecount(g)-1 */
735+ m = igraph_ecount (& gr -> g );
701736 }
702- m = igraph_vector_size (& v2 );
703737
704738 /* Create an appropriate iterator */
705739 if (PySlice_Check (item )) {
@@ -708,7 +742,7 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject
708742 PyObject * range ;
709743 igraph_bool_t ok ;
710744
711- ok = (PySlice_GetIndicesEx (item , igraph_vector_size ( & v2 ) , & start , & stop , & step , & sl ) == 0 );
745+ ok = (PySlice_GetIndicesEx (item , m , & start , & stop , & step , & sl ) == 0 );
712746 if (ok ) {
713747 range = igraphmodule_PyRange_create (start , stop , step );
714748 ok = (range != 0 );
@@ -720,7 +754,9 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject
720754 }
721755 if (!ok ) {
722756 igraph_vector_destroy (& v );
723- igraph_vector_destroy (& v2 );
757+ if (!working_on_whole_graph ) {
758+ igraph_vector_destroy (& v2 );
759+ }
724760 PyErr_SetString (PyExc_TypeError , "error while converting slice to iterator" );
725761 Py_DECREF (result );
726762 return 0 ;
@@ -733,13 +769,15 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject
733769 /* Did we manage to get an iterator? */
734770 if (iter == 0 ) {
735771 igraph_vector_destroy (& v );
736- igraph_vector_destroy (& v2 );
772+ if (!working_on_whole_graph ) {
773+ igraph_vector_destroy (& v2 );
774+ }
737775 PyErr_SetString (PyExc_TypeError , "invalid edge filter among positional arguments" );
738776 Py_DECREF (result );
739777 return 0 ;
740778 }
741779 /* Do the iteration */
742- while ((item2 = PyIter_Next (iter )) != 0 ) {
780+ while ((item2 = PyIter_Next (iter )) != 0 ) {
743781 if (igraphmodule_PyObject_to_integer_t (item2 , & igraph_idx )) {
744782 /* We simply ignore elements that we don't know */
745783 Py_DECREF (item2 );
@@ -750,28 +788,38 @@ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject
750788 Py_DECREF (result );
751789 Py_DECREF (iter );
752790 igraph_vector_destroy (& v );
753- igraph_vector_destroy (& v2 );
791+ if (!working_on_whole_graph ) {
792+ igraph_vector_destroy (& v2 );
793+ }
754794 return NULL ;
755795 }
756- if (igraph_vector_push_back (& v , VECTOR (v2 )[(long int ) igraph_idx ])) {
796+ if (igraph_vector_push_back (& v , working_on_whole_graph ? igraph_idx : VECTOR (v2 )[(long int ) igraph_idx ])) {
757797 Py_DECREF (result );
758798 Py_DECREF (iter );
759799 igraphmodule_handle_igraph_error ();
760800 igraph_vector_destroy (& v );
761- igraph_vector_destroy (& v2 );
801+ if (!working_on_whole_graph ) {
802+ igraph_vector_destroy (& v2 );
803+ }
762804 return NULL ;
763805 }
764806 }
765807 }
808+
766809 /* Deallocate stuff */
767- igraph_vector_destroy (& v2 );
810+ if (!working_on_whole_graph ) {
811+ igraph_vector_destroy (& v2 );
812+ }
813+
768814 Py_DECREF (iter );
769815 if (PyErr_Occurred ()) {
770816 igraph_vector_destroy (& v );
771817 Py_DECREF (result );
772818 return 0 ;
773819 }
820+
774821 igraph_es_destroy (& result -> es );
822+
775823 if (igraph_es_vector_copy (& result -> es , & v )) {
776824 Py_DECREF (result );
777825 igraphmodule_handle_igraph_error ();
0 commit comments