Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/installation_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Dependencies

The following software and modules are required to run dot2tex:

- Python_ 2.7 or 3.x.
- pyparsing_. Version 1.4.8 or later is recommended.
- Python_ 3.x.
- pyparsing_. Version 3.0 or later is required.
- Graphviz_. A recent version is required.
- preview_. A LaTeX package for extracting parts of a document. A free-standing part of the `preview-latex`_/`AUCTeX`_ bundle.
- `PGF/TikZ`_ version 2.0 or later.
Expand Down
102 changes: 42 additions & 60 deletions dot2tex/pgfformat.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging

from .base import DotConvBase, parse_drawstring, get_drawobj_lblstyle
from .utils import smart_float, nsplit, getboolattr, tikzify
from .base import DotConvBase, get_drawobj_lblstyle, parse_drawstring
from .utils import getboolattr, nsplit, smart_float, tikzify

log = logging.getLogger("dot2tex")

Expand Down Expand Up @@ -171,13 +171,16 @@ def __init__(self, options=None):
self.template = PGF210_TEMPLATE
else:
self.template = PGF_TEMPLATE
self.styles = dict(dashed='dashed', dotted='dotted',
bold='very thick', filled='fill', invis="",
rounded='rounded corners', )
self.dashstyles = dict(
dashed=r'\pgfsetdash{{3pt}{3pt}}{0pt}',
dotted=r'\pgfsetdash{{\pgflinewidth}{2pt}}{0pt}',
bold=r'\pgfsetlinewidth{1.2pt}')
self.styles = {
'dashed': 'dashed', 'dotted': 'dotted',
'bold': 'very thick', 'filled': 'fill', 'invis': '',
'rounded': 'rounded corners'
}
self.dashstyles = {
'dashed': r'\pgfsetdash{{3pt}{3pt}}{0pt}',
'dotted': r'\pgfsetdash{{\pgflinewidth}{2pt}}{0pt}',
'bold': r'\pgfsetlinewidth{1.2pt}'
}

def start_node(self, node):
# Todo: Should find a more elegant solution
Expand Down Expand Up @@ -267,12 +270,9 @@ def set_color(self, drawop):
return s

def set_style(self, drawop):
c, style = drawop
_, style = drawop
pgfstyle = self.dashstyles.get(style, "")
if pgfstyle:
return " %s\n" % pgfstyle
else:
return ""
return f" {pgfstyle}\n" if pgfstyle else ""

def filter_styles(self, style):
filtered_styles = []
Expand All @@ -299,36 +299,27 @@ def draw_with_opacity(self, pathstr, fill=False):
def draw_ellipse(self, drawop, style=None):
op, x, y, w, h = drawop
should_fill = (op == 'E')

if style:
stylestr = " [%s]" % style
else:
stylestr = ''
stylestr = f" [{style}]" if style else ''
return self.draw_with_opacity(
"%s (%sbp,%sbp) ellipse (%sbp and %sbp)" % (
stylestr, smart_float(x), smart_float(y),
smart_float(w), smart_float(h)),
fill=should_fill)
"%s (%sbp,%sbp) ellipse (%sbp and %sbp)" % (
stylestr, smart_float(x), smart_float(y),
smart_float(w), smart_float(h)),
fill=should_fill)

def draw_polygon(self, drawop, style=None):
op, points = drawop
pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
if op == 'P':
should_fill = True
else:
should_fill = False

if style:
stylestr = " [%s]" % style
else:
stylestr = ''
pp = ['(%sbp,%sbp)' % (smart_float(p0), smart_float(p1))
for p0, p1 in points]
should_fill = op == 'P'
stylestr = f" [{style}]" if style else ''
return self.draw_with_opacity(
"%s %s -- cycle" % (stylestr, " -- ".join(pp)),
fill=should_fill)

def draw_polyline(self, drawop, style=None):
op, points = drawop
pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1]))
for p in points]
stylestr = ''
return self.draw_with_opacity("%s %s" % (stylestr, " -- ".join(pp)))

Expand All @@ -350,7 +341,7 @@ def draw_text(self, drawop, style=None):
alignstr = "" # centered (default)
styles.append(alignstr)
styles.append(style)
lblstyle = ",".join([i for i in styles if i])
lblstyle = ",".join(i for i in styles if i)
if lblstyle:
lblstyle = '[' + lblstyle + ']'
s = " \\draw (%sbp,%sbp) node%s {%s};\n" % (smart_float(x), smart_float(y), lblstyle, text)
Expand Down Expand Up @@ -448,10 +439,7 @@ def draw_edge(self, edge):
# log.warning('label: %s', edgelabel)

lblstyle = get_drawobj_lblstyle(edge)
if lblstyle:
lblstyle = '[' + lblstyle + ']'
else:
lblstyle = ''
lblstyle = ('[' + lblstyle + ']') if lblstyle else ''
if edgelabel:
extra = " node%s {%s}" % (lblstyle, edgelabel)
src = pp[0]
Expand Down Expand Up @@ -496,24 +484,21 @@ def get_node_preproc_code(self, node):
text = node.attr.get('texlbl', '')
if lblstyle:
return " \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
else:
return r"\tikz \node {" + text + "};"
return r"\tikz \node {" + text + "};"

def get_edge_preproc_code(self, edge, attribute="texlbl"):
lblstyle = edge.attr.get('lblstyle', '')
text = edge.attr.get(attribute, '')
if lblstyle:
return " \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
else:
return r"\tikz \node " + "{" + text + "};"
return r"\tikz \node " + "{" + text + "};"

def get_graph_preproc_code(self, graph):
lblstyle = graph.attr.get('lblstyle', '')
text = graph.attr.get('texlbl', '')
if lblstyle:
return " \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
else:
return r"\tikz \node {" + text + "};"
return r"\tikz \node {" + text + "};"


TIKZ_TEMPLATE = r"""\documentclass{standalone}
Expand Down Expand Up @@ -699,13 +684,16 @@ def __init__(self, options=None):
self.template = TIKZ_TEMPLATE
DotConvBase.__init__(self, options)

self.styles = dict(dashed='dashed', dotted='dotted',
bold='very thick', filled='fill', invis="", invisible="",
rounded='rounded corners', )
self.dashstyles = dict(
dashed=r'\pgfsetdash{{3pt}{3pt}}{0pt}',
dotted=r'\pgfsetdash{{\pgflinewidth}{2pt}}{0pt}',
bold=r'\pgfsetlinewidth{1.2pt}')
self.styles = {
'dashed': 'dashed', 'dotted': 'dotted',
'bold': 'very thick', 'filled': 'fill', 'invis': '',
'invisible': '', 'rounded': 'rounded corners'
}
self.dashstyles = {
'dashed': r'\pgfsetdash{{3pt}{3pt}}{0pt}',
'dotted': r'\pgfsetdash{{\pgflinewidth}{2pt}}{0pt}',
'bold': r'\pgfsetlinewidth{1.2pt}'
}

def set_options(self):
Dot2PGFConv.set_options(self)
Expand Down Expand Up @@ -784,10 +772,7 @@ def do_nodes(self):
if not pos:
continue
x, y = pos.split(',')
if dotshape != 'point':
label = self.get_label(node)
else:
label = ''
label = '' if dotshape == 'point' else self.get_label(node)

pos = "%sbp,%sbp" % (smart_float(x), smart_float(y))
style = node.attr.get('style') or ""
Expand Down Expand Up @@ -942,10 +927,7 @@ def draw_edge(self, edge):
edgelabel = self.get_label(edge)
# log.warning('label: %s', edgelabel)
lblstyle = get_drawobj_lblstyle(edge, extra_styles=edge.attr.get('exstyle'))
if lblstyle:
lblstyle = '[' + lblstyle + ']'
else:
lblstyle = ''
lblstyle = ('[' + lblstyle + ']') if lblstyle else ''
if edgelabel:
extra = " node%s {%s}" % (lblstyle, edgelabel)

Expand Down
41 changes: 41 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "dot2tex"
version = '2.12.0'

description = "A Graphviz to LaTeX converter"
readme = "readme.md"
requires-python = ">=3.7"
dependencies = [
"pyparsing >= 3.0",
]
authors = [
{name = "Kjell Magne Fauske", email = "kjellmf@gmail.com"},
]
license = "MIT"

classifiers = [
'Development Status :: 4 - Beta',
'Environment :: Console',
'Intended Audience :: Science/Research',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Topic :: Scientific/Engineering :: Visualization',
'Topic :: Text Processing :: Markup :: LaTeX',
'Topic :: Utilities',
]

[project.urls]
"Homepage" = "https://github.com/sagemath/dot2tex"

[project.scripts]
dot2tex = "dot2tex.dot2tex:main"

[project.optional-dependencies]
test = [
"pytest",
]
3 changes: 1 addition & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ Before you install dot2tex you have to have a working Python environment
installed on your system. Dot2tex works with Python 3. In addition
you will need the following modules:

* [pyparsing](https://github.com/pyparsing/pyparsing). A recent version is required.
Older version like for instance 1.3.2 does not work with dot2tex.
* [pyparsing](https://github.com/pyparsing/pyparsing). A recent version is required, at least version 3.0.
* [preview](https://ctan.org/pkg/preview)
A stand-alone part of the preview-latex bundle.
Required for preprocessing graphs with LaTeX.
Expand Down
43 changes: 0 additions & 43 deletions setup.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/experimental/test_comparedotparsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def test_subgraphs(self):
def test_quoting(self):
self.assertEqual(test_dotfile("quoting.dot"), 1)

# the following three files are missing, so desactivate
# the following three files are missing, so deactivate

# def test_unicode1(self):
# self.assertEqual(test_dotfile("unicode1.dot"), 1)
Expand Down
Loading