If you are thinking about subclassing
Graph into an
ImmutableGraph, you could also subclass it in a way that you add the hook function and make
add_edges() and all the other functions call this hook function. It might not catch all cases where a graph can get modified; the C core of igraph can easily call
igraph_add_vertices() and other functions on a low-level graph directly, without going through the Python layer, but this is probably rare enough that you don’t need to care about it too much if you would like to implement it only for your own purposes. However, for a long-term solution that eventually gets merged into
python-igraph, I think it is inevitable to add this functionality directly to the C core of the library because that’s the part where all the modifications to the graph must eventually go through.
In fact, there is already a mechanism similar to the one proposed here in the C core library; it is called the attribute handler interface. Its purpose is to allow higher-level interfaces implement their own attribute storage mechanism and to get notified about changes in the underlying graph structure so they can adjust the attributes; for instance, if some vertices are deleted, the Python attribute handler gets called via its
permute_vertices() method (in C) and this is how the Python interfaces gets to know that the attributes corresponding to the deleted vertices should be removed from the attribute storage.
I believe that in the end the optimal solution would be either:
- to allow the user to extend the basic Python attribute handler in Python, either globally or on a per-graph basis (but then this would be limited to the Python interface only), or
- to re-purpose the attribute handler table in the C layer as some kind of “event handler interface”; the attribute handler table would then be just one kind of event handler that is interested in changes happening to graph objects, and allow the user to register additional event handlers on graphs, either globally or on a per-graph basis. The advantage would be that higher-level interfaces would benefit from this as well, not only the Python interface.
@szhorvat What do you think? We have also talked about caching certain graph properties inside the
igraph_t graph object (e.g., whether the graph is simple, whether the graph is a DAG etc). This caching mechanism could also be implemented in terms of a generic event handler where the graph property cach gets invalidated if certain events happen to the graph.