networkx icon indicating copy to clipboard operation
networkx copied to clipboard

Pydot - Valid Labels and Tooltips With Colon ( ":" ) Fail Since Networkx-2.8.4

Open chrizzFTD opened this issue 2 years ago • 1 comments

Hello networkx team,

Thanks for this project!

Recent updates like those from https://github.com/networkx/networkx/pull/5710, Catch ':' explicitly while working with pydot, seem to be too aggressive as previous valid code like this started failing since networkx==2.8.4:

nodes_info = {
    1: dict(
        label="{<0>x:y:z|<1>z}",
        tooltip=r"Stack:&#10;0: x:y:z&#10;1: b:\...\z.ext&#10;2: b:\...\z.ext",
        style='"rounded,filled"',
        shape="record",
    ),
    2: dict(
        label="{<0>a|<1>b}",
        tooltip=r"Stack:&#10;0: b:\...\a.ext&#10;1: b:\...\b.ext",
        style='"rounded,filled"',
        shape="record",
    ),
}
edges_info = (
    (1, 1, dict(color='"sienna:crimson:orange"')),
    (1, 2, dict(color='crimson')),
)
import networkx as nx
graph = nx.MultiDiGraph()
graph.add_nodes_from(nodes_info.items())
graph.add_edges_from(edges_info)

import tempfile
fd, fp = tempfile.mkstemp()

from networkx.drawing import nx_pydot
nx_pydot.write_dot(graph, fp)
print(f"Written to {fp}")

Current Behavior

Running the above code snippet fails with versions after networkx==2.8.3 (tested with2.8.4 and 2.8.6):

(py310usd2208) C:\Users\Christian>python -m pip install networkx==2.8.4
Collecting networkx==2.8.4
  Using cached networkx-2.8.4-py3-none-any.whl (2.0 MB)
Installing collected packages: networkx
Successfully installed networkx-2.8.4

(py310usd2208) C:\Users\Christian>python B:\write\code\git\grillbkp\network_broken.py
Traceback (most recent call last):
  File "B:\write\code\git\grillbkp\network_broken.py", line 28, in <module>
    nx_pydot.write_dot(graph, fp)
  File "C:\Users\Christian\.conda\envs\py310usd2208\lib\site-packages\networkx\utils\decorators.py", line 845, in func
    return argmap._lazy_compile(__wrapper)(*args, **kwargs)
  File "<class 'networkx.utils.decorators.argmap'> compilation 5", line 5, in argmap_write_dot_1
  File "C:\Users\Christian\.conda\envs\py310usd2208\lib\site-packages\networkx\drawing\nx_pydot.py", line 51, in write_dot
    P = to_pydot(G)
  File "C:\Users\Christian\.conda\envs\py310usd2208\lib\site-packages\networkx\drawing\nx_pydot.py", line 263, in to_pydot
    raise ValueError(
ValueError: Node names and attributes should not contain ":" unless they are quoted with "".                For example the string 'attribute:data1' should be written as '"attribute:data1"'.                Please refer https://github.com/pydot/pydot/issues/258

While this ValueError message is more descriptive than what would appear on failures described on https://github.com/pydot/pydot/issues/258:

Error: file.dot: syntax error in line x near ':'

This syntax error was not there for all attributes (e.g. fillcolor had this issue and had to be wrapped in quotes, but label and tooltip would work just fine), so this is now raising false positives for previously working attributes.

Expected Behavior

Code to continue working as it did with networkx==2.8.3 and previous versions, which produce the expected graphviz content:

digraph  {
1 [label="{<0>x:y:z|<1>z}", shape=record, style="rounded,filled", tooltip="Stack:&#10;0: x:y:z&#10;1: b:\...\z.ext&#10;2: b:\...\z.ext"];
2 [label="{<0>a|<1>b}", shape=record, style="rounded,filled", tooltip="Stack:&#10;0: b:\...\a.ext&#10;1: b:\...\b.ext"];
1 -> 1  [color="sienna:crimson:orange", key=0];
1 -> 2  [color=crimson, key=0];
}

image

(py310usd2208) C:\Users\Christian>python -m pip install networkx==2.8.3
Collecting networkx==2.8.3
  Using cached networkx-2.8.3-py3-none-any.whl (2.0 MB)
Installing collected packages: networkx
Successfully installed networkx-2.8.3

(py310usd2208) C:\Users\Christian>python B:\write\code\git\grillbkp\network_broken.py
Written to C:\Users\CHRIST~1\AppData\Local\Temp\tmp4nhoqbx_

Steps to Reproduce

  1. python -m pip install networkx==2.8.6
  2. Run python snippet above

Environment

Python version: Python 3.10.4 NetworkX version: networkx 2.8.6

Additional context

This was raised on https://github.com/networkx/networkx/issues/5662#issuecomment-1189782037 and while https://github.com/networkx/networkx/issues/5723 suggests to deprecate pydot, would it be a better strategy to maintain backwards compatibility by either logging warnings instead of raising an exception, or excluding known working attributes like tooltip or label from the : check?

Kind regards,

chrizzFTD avatar Sep 04 '22 10:09 chrizzFTD

would it be a better strategy to maintain backwards compatibility by either logging warnings instead of raising an exception, or excluding known working attributes like tooltip or label from the : check?

The general problem with pydot is that there were changes associated with an updated version of pyparsing on which pydot depends that resulted in behavior changes. Things like #5710 are an attempt on NetworkX's end to work around these limitations, but unfortunately the changes are more extensive (for example, NetworkX's nx_pydot test suite is currently xfailed and has been failing since the release of pyparsing 3.0.2).

The decision to deprecate pydot is largely motivated by the fact that the project does not seem to be maintained, and the workarounds that have been attempted by NetworkX have their own associated issues as mentioned here and elsewhere.

rossbar avatar Sep 07 '22 05:09 rossbar

Thanks a lot for that additional context, @rossbar, I'll close this issue and keep an eye on the one for pydot deprecation from https://github.com/networkx/networkx/issues/5723

chrizzFTD avatar Sep 24 '22 00:09 chrizzFTD