Making not_implemented_for decorator depend on dispatchable functions for non-nx graphs
This PR is a follow up from https://github.com/networkx/networkx/issues/8030. It makes nx.is_multigraph and nx.is_directed function dispatchable so its behavior can be modified by custom backends. In addition to this, it makes not_implemented_for decorator depend on nx.is_multigraph and nx.is_directed. The change allows backends graph class to not be forced to implement is_directed and is_multigraph methods, they just need to define its custom behavior based on the new dispatchable functions.
Previous approach remains the recommended way and not_implemented_for decorator will first attempt to use graph methods is_directed and is_multigraph. Fallback to top-level nx.is_directed and nx.is_multigraph only happens if the graph object functions are not present. This avoids calling the dispatchable NetworkX functions, which might not be implemented for some backends and could trigger unnecessary conversions to NetworkX graphs.
@eriknw @dschult any change you can take a look at this small one? This should remove the limitation/restriction for backend graph types to implement is_directed and is_multigraph
IIUC, this is basically "moving" the requirement for
is_directedandis_multigraphfrom methods on the backend graph class to functions in the backend. From the perspective of the backend implementer I don't see how this changes much - no matter what, I have to have anis_directedandis_multigraphmethod/function in order to get past thenot_implemented_fordecorator, right?In other words - if a backend implementer follows the current recommendation (that their backend graph object implements a
is_directedandis_multigraphmethod) then everthing currently works, correct?
Sorry @rossbar I missed this comment! What I am trying to do here is to pass a class that is not defined in my code but in an external library. For example, my backend class is PyGraph from rustworkx.
I was able to fix it by monkey patching the external library to have this method but I'd prefer to not need that. Also, other classes might not admit patching in case the user wants to use built-in types for dispatching. For example, if you want nerworkx to work directly from dicts or strings.