99import os
1010import re
1111from typing import Any , Callable , List , Mapping , Tuple , Union
12- from urllib .parse import urlencode
1312
1413import networkx
1514import pydot
@@ -195,6 +194,15 @@ def as_identifier(s):
195194 return s
196195
197196
197+ # # TODO: plot meths with PlotContext
198+ # PlotContext = namedtuple(
199+ # "PlotContext", "inputs, outputs, solution, node_props, edge_props, clusters"
200+ # )
201+ # plot_context = PlotContext(
202+ # inputs, outputs, solution, node_props, edge_props, clusters
203+ # )
204+
205+
198206def build_pydot (
199207 graph : networkx .Graph ,
200208 name = None ,
@@ -285,9 +293,6 @@ def get_node_name(a):
285293 if nx_node in getattr (solution , "overwrites" , ())
286294 else fill_color
287295 )
288- ## NOTE: SVG tooltips not working without URL:
289- # https://gitlab.com/graphviz/graphviz/issues/1425
290- kw ["tooltip" ] = html .escape (str (solution .get (nx_node )))
291296
292297 else : # Operation
293298 kw = {
@@ -308,19 +313,25 @@ def get_node_name(a):
308313 kw ["style" ] = "filled"
309314 kw ["fillcolor" ] = cancel_color
310315
311- try :
312- filename = urlencode (inspect .getfile (nx_node .fn ))
313- kw ["URL" ] = f"file://{ filename } "
314- except Exception as ex :
315- log .debug ("Ignoring error while inspecting file of %s: %s" , nx_node , ex )
316- try :
317- fn_tooltip = inspect .getsource (nx_node .fn )
318- except Exception as ex :
319- log .debug (
320- "Ignoring error while inspecting source of %s: %s" , nx_node , ex
321- )
322- fn_tooltip = str (nx_node )
323- kw ["tooltip" ] = html .escape (fn_tooltip )
316+ # TODO: move `node_props` in a cloned networkX.
317+ if (
318+ not node_props
319+ or nx_node not in node_props
320+ or "URL" not in node_props [nx_node ]
321+ ):
322+ url = _get_node_url (nx_node )
323+ if url :
324+ kw ["URL" ] = url
325+
326+ # TODO: move `node_props` in a cloned networkX.
327+ if (
328+ not node_props
329+ or nx_node not in node_props
330+ or "tooltip" not in node_props [nx_node ]
331+ ):
332+ tooltip = _get_node_tooltip (nx_node , solution )
333+ if tooltip :
334+ kw ["tooltip" ] = tooltip
324335
325336 node = pydot .Node (** kw ,)
326337 _apply_user_props (node , node_props , key = node .get_name ())
@@ -390,6 +401,44 @@ def get_node_name(a):
390401 return dot
391402
392403
404+ def _get_node_url (nx_node ) -> Union [str , None ]:
405+ """
406+ Default applied on all nodes if `URL` not in `node_props`.
407+ """
408+ if isinstance (nx_node , Operation ):
409+ try :
410+ filename = inspect .getfile (nx_node .fn )
411+ ## TODO: hook sphinx to link nodes to generated documentation
412+ ## NOTE: Jupyter lab is blocking local-urls (e.g. on SVGs).
413+ return html .escape (f"file://{ filename } " )
414+ except Exception as ex :
415+ log .debug ("Ignoring error while inspecting file of %s: %s" , nx_node , ex )
416+
417+
418+ def _get_node_tooltip (nx_node , sol : dict ) -> Union [str , None ]:
419+ """
420+ Default applied on all nodes if `tooltip` not in `node_props`.
421+
422+ .. Note::
423+ SVG tooltips may not work without URL on PDFs:
424+ https://gitlab.com/graphviz/graphviz/issues/1425
425+ """
426+ txt = None
427+ if isinstance (nx_node , Operation ):
428+ try :
429+ txt = inspect .getsource (nx_node .fn )
430+ except Exception as ex :
431+ log .debug ("Ignoring error while inspecting source of %s: %s" , nx_node , ex )
432+ txt = str (nx_node )
433+ else :
434+ if sol is not None :
435+ val = sol .get (nx_node )
436+ txt = "None" if val is None else f"({ type (val ).__name__ } ) { val } "
437+
438+ if txt :
439+ return html .escape (txt )
440+
441+
393442def supported_plot_formats () -> List [str ]:
394443 """return automatically all `pydot` extensions"""
395444 return [".%s" % f for f in pydot .Dot ().formats ]
0 commit comments