jrfonseca / xdot.py

Interactive viewer for graphs written in Graphviz's dot language.
GNU Lesser General Public License v3.0
870 stars 146 forks source link

Parser(?) error: unknown xdot opcode '0' #92

Closed gerion0 closed 3 years ago

gerion0 commented 3 years ago

With the current xdot (git HEAD), I got this behaviour:

test.dot

digraph "test" {
   1 [label="a\\00"]
}
$ xdot test.dot
error: unknown xdot opcode '0'

test2.dot

digraph "test" {
   1 [label="a\\b"]
}
$ xdot test2.dot
Traceback (most recent call last):
  File "/usr/lib/python-exec/python3.9/xdot", line 33, in <module>
    sys.exit(load_entry_point('xdot==1.2', 'gui_scripts', 'xdot')())
  File "/usr/lib/python3.9/site-packages/xdot/__main__.py", line 81, in main
    win.open_file(inputfile)
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 711, in open_file
    self.set_dotcode(fp.read(), filename)
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 693, in set_dotcode
    if self.dotwidget.set_dotcode(dotcode, filename):
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 146, in set_dotcode
    if self._set_dotcode(dotcode, filename, center=center):
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 137, in _set_dotcode
    self.set_xdotcode(xdotcode, center=center)
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 157, in set_xdotcode
    self.graph = parser.parse()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 535, in parse
    DotParser.parse(self)
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 309, in parse
    self.parse_graph()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 318, in parse_graph
    self.parse_stmt()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 367, in parse_stmt
    self.handle_node(id, attrs)
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 505, in handle_node
    shapes.extend(parser.parse())
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 217, in parse
    points = self.read_polygon()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 132, in read_polygon
    n = self.read_int()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 112, in read_int
    return int(self.read_code())
ValueError: invalid literal for int() with base 10: ''

graphviz itself (plain dot) handles both files fine.

jrfonseca commented 3 years ago

This works now for me.

I believe this is a duplicate of https://github.com/jrfonseca/xdot.py/issues/19 which was fixed in graphviz eventually. graphviz handles this correctly for png/svg/etc but the xdot output it produces is invalid.

You should just ensure you have a more recent version of graphviz.

gerion0 commented 3 years ago

The mentioned fix was added to graphviz wth commit 9ea83477 which was released in 2.46.0. I have tried the above minimal example with graphviz 2.48.0 with exactly the same error. The above stack trace indicates that the parsing is done interally not by graphviz. Can you take a look at it again?

jrfonseca commented 3 years ago

I was actually testing here with graphviz 2.43.0. So it does seem this is a different issue, perhaps due to a regression in upstream graphviz between 2.43 and 2.48.

This is the xdot output from graphviz 2.43.0:

$ cat tests/issue_92.dot
digraph "test" {
   1 [label="a\\00"]
}
$ dot -T xdot tests/issue_92.dot
digraph test {
    graph [_draw_="c 9 -#fffffe00 C 7 -#ffffff P 4 0 0 0 36 54 36 54 0 ",
        bb="0,0,54,36",
        xdotversion=1.7
    ];
    node [label="\N"];
    1   [_draw_="c 7 -#000000 e 27 18 27 18 ",
        _ldraw_="F 14 11 -Times-Roman c 7 -#000000 T 27 14.3 0 24 4 -a\00 ",
        height=0.5,
        label="a\\00",
        pos="27,18",
        width=0.75];
}

Could you please paste what you get from graphviz 2.48.0?

gerion0 commented 3 years ago

This is my output:

$ cat test.dot
digraph "test" {
   1 [label="a\\00"]
}
$ dot -T xdot test.dot
digraph test {
    graph [_draw_="c 9 -#fffffe00 C 7 -#ffffff P 4 0 0 0 36 61.09 36 61.09 0 ",
        bb="0,0,61.095,36",
        xdotversion=1.7
    ];
    node [label="\N"];
    1   [_draw_="c 7 -#000000 e 30.55 18 30.59 18 ",
        _ldraw_="F 14 11 -Times-Roman c 7 -#000000 T 30.55 14.3 0 31 4 -a\\00 ",
        height=0.5,
        label="a\\00",
        pos="30.547,18",
        width=0.84854];
}
$ xdot test.dot
error: unknown xdot opcode '0
$ cat test2.dot
digraph "test" {
   1 [label="a\\b"]
}
$ dot -T xdot test2.dot
digraph test {
    graph [_draw_="c 9 -#fffffe00 C 7 -#ffffff P 4 0 0 0 36 54 36 54 0 ",
        bb="0,0,54,36",
        xdotversion=1.7
    ];
    node [label="\N"];
    1   [_draw_="c 7 -#000000 e 27 18 27 18 ",
        _ldraw_="F 14 11 -Times-Roman c 7 -#000000 T 27 14.3 0 22 3 -a\\b ",
        height=0.5,
        label="a\\b",
        pos="27,18",
        width=0.75];
}
$ xdot test2.dot
Traceback (most recent call last):
  File "/usr/lib/python-exec/python3.9/xdot", line 33, in <module>
    sys.exit(load_entry_point('xdot==1.2', 'gui_scripts', 'xdot')())
  File "/usr/lib/python3.9/site-packages/xdot/__main__.py", line 81, in main
    win.open_file(inputfile)
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 711, in open_file
    self.set_dotcode(fp.read(), filename)
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 693, in set_dotcode
    if self.dotwidget.set_dotcode(dotcode, filename):
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 146, in set_dotcode
    if self._set_dotcode(dotcode, filename, center=center):
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 137, in _set_dotcode
    self.set_xdotcode(xdotcode, center=center)
  File "/usr/lib/python3.9/site-packages/xdot/ui/window.py", line 157, in set_xdotcode
    self.graph = parser.parse()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 536, in parse
    DotParser.parse(self)
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 309, in parse
    self.parse_graph()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 318, in parse_graph
    self.parse_stmt()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 367, in parse_stmt
    self.handle_node(id, attrs)
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 506, in handle_node
    shapes.extend(parser.parse())
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 217, in parse
    points = self.read_polygon()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 132, in read_polygon
    n = self.read_int()
  File "/usr/lib/python3.9/site-packages/xdot/dot/parser.py", line 112, in read_int
    return int(self.read_code())
ValueError: invalid literal for int() with base 10: ''
$ dot -v
dot - graphviz version 2.48.0 (20210717.1556)
libdir = "/usr/lib64/graphviz"
Activated plugin library: libgvplugin_dot_layout.so.6
Using layout: dot:dot_layout
Activated plugin library: libgvplugin_core.so.6
Using render: dot:core
Using device: dot:dot:core
The plugin configuration file:
    /usr/lib64/graphviz/config6
        was successfully loaded.
    render  :  cairo dot dot_json fig gd json json0 map mp pic pov ps svg tk vml vrml xdot xdot_json
    layout  :  circo dot fdp neato nop nop1 nop2 osage patchwork sfdp twopi
    textlayout  :  textlayout
    device  :  bmp canon cmap cmapx cmapx_np dot dot_json eps fig gd gd2 gif gtk gv ico imap imap_np ismap jpe jpeg jpg json json0 mp pdf pic plain plain-ext png pov ps ps2 svg svgz tif tiff tk vml vmlz vrml wbmp x11 xdot xdot1.2 xdot1.4 xdot_json xlib
    loadimage   :  (lib) bmp eps gd gd2 gif ico jpe jpeg jpg pdf png ps svg xbm
jrfonseca commented 3 years ago

Thanks. I see what's happening.

This is a direct consequence of https://github.com/jrfonseca/xdot.py/issues/19 's graphviz fix. xdot.py was expecting badly escaped backslashes (which sort of worked in some cases), but now it needs to expect properly escaped backslashes.

My only question are: Can we just assume backslashes are properly escaped? If not, what's the best way to detect? (Because unfortunately xdotversion was not bumped when this issue was fixed.)

gerion0 commented 3 years ago

Can't you just ask dot/graphviz itself for its version? The fix is directly dependent of a graphviz release.

jrfonseca commented 3 years ago

Can't you just ask dot/graphviz itself for its version? The fix is directly dependent of a graphviz release.

Good point. I did just that.

It should be fixed now. Thanks