11from __future__ import annotations
22
3- from ctypes import pointer , c_int
3+ from ctypes import cast , pointer , c_void_p
44from math import nan
55from typing import Any , Callable , Optional , TYPE_CHECKING
66
1010 numpy_array_to_igraph_vector_t_view ,
1111)
1212from igraph_ctypes ._internal .enums import AttributeElementType , AttributeType
13+ from igraph_ctypes ._internal .functions import igraph_ecount , igraph_vcount
1314from igraph_ctypes ._internal .lib import (
1415 igraph_error ,
1516 igraph_es_as_vector ,
2728 igraph_strvector_push_back ,
2829 igraph_strvector_set ,
2930)
30- from igraph_ctypes ._internal .types import igraph_attribute_table_t , igraph_bool_t
31+ from igraph_ctypes ._internal .types import (
32+ igraph_attribute_table_t ,
33+ igraph_bool_t ,
34+ )
3135from igraph_ctypes ._internal .utils import nop , protect_with , protect_with_default
3236
3337from .storage import (
@@ -59,6 +63,10 @@ def _trigger_error(error: int) -> int:
5963 )
6064
6165
66+ def _are_pointers_equal (foo , bar ):
67+ return cast (foo , c_void_p ).value == cast (bar , c_void_p ).value
68+
69+
6270class AttributeHandlerBase :
6371 """Base class for igraph attribute handlers."""
6472
@@ -122,9 +130,18 @@ def copy(
122130 copy_edge_attributes : bool ,
123131 ):
124132 storage = get_storage_from_graph (graph )
125- new_storage = storage .copy (
126- copy_graph_attributes , copy_vertex_attributes , copy_edge_attributes
127- )
133+
134+ if copy_vertex_attributes :
135+ new_vcount = - 1
136+ else :
137+ new_vcount = int (igraph_vcount (to ))
138+
139+ if copy_edge_attributes :
140+ new_ecount = - 1
141+ else :
142+ new_ecount = int (igraph_ecount (to ))
143+
144+ new_storage = storage .copy (copy_graph_attributes , new_vcount , new_ecount )
128145 assign_storage_to_graph (to , new_storage )
129146
130147 def add_vertices (self , graph , n : int , attr ) -> None :
@@ -139,10 +156,17 @@ def add_vertices(self, graph, n: int, attr) -> None:
139156 get_storage_from_graph (graph ).add_vertices (graph , n )
140157
141158 def permute_vertices (self , graph , to , mapping ):
142- pass
159+ mapping_array = igraph_vector_int_t_to_numpy_array_view (mapping )
160+
161+ old_attrs = get_storage_from_graph (graph ).get_vertex_attribute_map ()
162+ new_attrs = get_storage_from_graph (to ).get_vertex_attribute_map ()
163+
164+ # The code below works for graph == to and graph != to as well
165+ for name , values in old_attrs .items ():
166+ new_attrs .set (name , values [mapping_array ], _check_length = False )
143167
144168 def combine_vertices (self , graph , to , mapping , combinations ):
145- pass
169+ assert not _are_pointers_equal ( graph , to )
146170
147171 def add_edges (self , graph , edges , attr ) -> None :
148172 # attr will only ever be NULL here so raise an error if it is not
@@ -157,10 +181,17 @@ def add_edges(self, graph, edges, attr) -> None:
157181 get_storage_from_graph (graph ).add_edges (graph , edge_array )
158182
159183 def permute_edges (self , graph , to , mapping ):
160- pass
184+ mapping_array = igraph_vector_int_t_to_numpy_array_view (mapping )
185+
186+ old_attrs = get_storage_from_graph (graph ).get_edge_attribute_map ()
187+ new_attrs = get_storage_from_graph (to ).get_edge_attribute_map ()
188+
189+ # The code below works for graph == to and graph != to as well
190+ for name , values in old_attrs .items ():
191+ new_attrs .set (name , values [mapping_array ], _check_length = False )
161192
162193 def combine_edges (self , graph , to , mapping , combinations ):
163- pass
194+ assert not _are_pointers_equal ( graph , to )
164195
165196 def get_info (self , graph , gnames , gtypes , vnames , vtypes , enames , etypes ):
166197 storage = get_storage_from_graph (graph )
0 commit comments