[blockdiag] 04/29: Import Upstream version 1.1.4
Andreas Tille
tille at debian.org
Tue Jan 10 21:35:57 UTC 2017
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository blockdiag.
commit fdb8942a1d234431d73001f81b2f3904cbbd09ef
Author: Andreas Tille <tille at debian.org>
Date: Tue Jan 10 11:08:02 2017 +0100
Import Upstream version 1.1.4
---
PKG-INFO | 14 +++-
blockdiag.1 | 6 ++
src/README.txt | 12 +++
src/blockdiag.egg-info/PKG-INFO | 14 +++-
src/blockdiag.egg-info/SOURCES.txt | 2 +
src/blockdiag/__init__.py | 2 +-
src/blockdiag/builder.py | 19 ++---
src/blockdiag/command.py | 3 +-
src/blockdiag/drawer.py | 10 +--
src/blockdiag/elements.py | 49 +++++++++--
src/blockdiag/imagedraw/pdf.py | 6 ++
src/blockdiag/imagedraw/png.py | 14 +++-
src/blockdiag/imagedraw/svg.py | 6 ++
src/blockdiag/metrics.py | 76 ++++++++++++++++-
src/blockdiag/noderenderer/__init__.py | 2 +-
src/blockdiag/noderenderer/actor.py | 16 ++--
src/blockdiag/parser.py | 5 +-
src/blockdiag/tests/diagrams/circular_ref2.diag | 4 +
src/blockdiag/tests/diagrams/edge_datamodels.diag | 3 +
src/blockdiag/tests/test_boot_params.py | 17 ++++
src/blockdiag/tests/test_builder.py | 12 ++-
src/blockdiag/tests/test_rst_directives.py | 99 ++++++++++++++++++++++-
src/blockdiag/utils/bootstrap.py | 13 ++-
src/blockdiag/utils/rst/directives.py | 32 +++++++-
24 files changed, 384 insertions(+), 52 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index 89eb60a..6575733 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: blockdiag
-Version: 1.1.2
+Version: 1.1.4
Summary: blockdiag generate block-diagram image file from spec-text file.
Home-page: http://blockdiag.com/
Author: Takeshi Komiya
@@ -121,6 +121,18 @@ Description: `blockdiag` generate block-diagram image file from spec-text file.
History
=======
+ 1.1.4 (2012-03-15)
+ ------------------
+ * Add new edge.hstyles: oneone, onemany, manyone, manymany
+ * Add edge attribute: description (for build description-tables)
+ * Fix bugs
+
+ 1.1.3 (2012-02-13)
+ ------------------
+ * Add new edge type for data-models (thanks to David Lang)
+ * Add --no-transparency option
+ * Fix bugs
+
1.1.2 (2011-12-26)
------------------
* Support font-index for TrueType Font Collections (.ttc file)
diff --git a/blockdiag.1 b/blockdiag.1
index 3f0b711..511029a 100644
--- a/blockdiag.1
+++ b/blockdiag.1
@@ -53,6 +53,9 @@ write diagram to FILE
.B \-f FONT, \-\-font=FONT
use FONT to draw diagram
.TP
+.B \-\-fontmap=FONT
+use FONTMAP file to draw diagram
+.TP
.B \-s, \-\-separate
Separate diagram images for each group
.TP
@@ -61,6 +64,9 @@ Output diagram as TYPE format
.TP
.B \-\-nodoctype
Do not output doctype definition tags (SVG only)
+.TP
+.B \-\-no-transparency
+do not make transparent background of diagram (PNG only)
.SH SEE ALSO
The programs are documented fully by
.br
diff --git a/src/README.txt b/src/README.txt
index fbb9010..cf3744b 100644
--- a/src/README.txt
+++ b/src/README.txt
@@ -113,6 +113,18 @@ Apache License 2.0
History
=======
+1.1.4 (2012-03-15)
+------------------
+* Add new edge.hstyles: oneone, onemany, manyone, manymany
+* Add edge attribute: description (for build description-tables)
+* Fix bugs
+
+1.1.3 (2012-02-13)
+------------------
+* Add new edge type for data-models (thanks to David Lang)
+* Add --no-transparency option
+* Fix bugs
+
1.1.2 (2011-12-26)
------------------
* Support font-index for TrueType Font Collections (.ttc file)
diff --git a/src/blockdiag.egg-info/PKG-INFO b/src/blockdiag.egg-info/PKG-INFO
index 89eb60a..6575733 100644
--- a/src/blockdiag.egg-info/PKG-INFO
+++ b/src/blockdiag.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: blockdiag
-Version: 1.1.2
+Version: 1.1.4
Summary: blockdiag generate block-diagram image file from spec-text file.
Home-page: http://blockdiag.com/
Author: Takeshi Komiya
@@ -121,6 +121,18 @@ Description: `blockdiag` generate block-diagram image file from spec-text file.
History
=======
+ 1.1.4 (2012-03-15)
+ ------------------
+ * Add new edge.hstyles: oneone, onemany, manyone, manymany
+ * Add edge attribute: description (for build description-tables)
+ * Fix bugs
+
+ 1.1.3 (2012-02-13)
+ ------------------
+ * Add new edge type for data-models (thanks to David Lang)
+ * Add --no-transparency option
+ * Fix bugs
+
1.1.2 (2011-12-26)
------------------
* Support font-index for TrueType Font Collections (.ttc file)
diff --git a/src/blockdiag.egg-info/SOURCES.txt b/src/blockdiag.egg-info/SOURCES.txt
index fadb6a7..77aa2f1 100644
--- a/src/blockdiag.egg-info/SOURCES.txt
+++ b/src/blockdiag.egg-info/SOURCES.txt
@@ -90,6 +90,7 @@ src/blockdiag/tests/diagrams/background_url_image.diag
src/blockdiag/tests/diagrams/beginpoint_color.diag
src/blockdiag/tests/diagrams/branched.diag
src/blockdiag/tests/diagrams/circular_ref.diag
+src/blockdiag/tests/diagrams/circular_ref2.diag
src/blockdiag/tests/diagrams/circular_ref_and_parent_node.diag
src/blockdiag/tests/diagrams/circular_ref_to_root.diag
src/blockdiag/tests/diagrams/circular_skipped_edge.diag
@@ -98,6 +99,7 @@ src/blockdiag/tests/diagrams/diagram_attributes.diag
src/blockdiag/tests/diagrams/diagram_attributes_order.diag
src/blockdiag/tests/diagrams/diagram_orientation.diag
src/blockdiag/tests/diagrams/edge_attribute.diag
+src/blockdiag/tests/diagrams/edge_datamodels.diag
src/blockdiag/tests/diagrams/edge_label.diag
src/blockdiag/tests/diagrams/edge_layout_landscape.diag
src/blockdiag/tests/diagrams/edge_layout_portrait.diag
diff --git a/src/blockdiag/__init__.py b/src/blockdiag/__init__.py
index 40e1275..c070b78 100644
--- a/src/blockdiag/__init__.py
+++ b/src/blockdiag/__init__.py
@@ -13,4 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-__version__ = '1.1.2'
+__version__ = '1.1.4'
diff --git a/src/blockdiag/builder.py b/src/blockdiag/builder.py
index 4481585..4639319 100644
--- a/src/blockdiag/builder.py
+++ b/src/blockdiag/builder.py
@@ -172,13 +172,13 @@ class DiagramLayoutManager:
def do_layout(self):
self.detect_circulars()
- self.set_node_width()
+ self.set_node_xpos()
self.adjust_node_order()
height = 0
for node in self.diagram.nodes:
if node.xy.x == 0:
- self.set_node_height(node, height)
+ self.set_node_ypos(node, height)
height = max(xy.y for xy in self.coordinates) + 1
def get_related_nodes(self, node, parent=False, child=False):
@@ -236,7 +236,8 @@ class DiagramLayoutManager:
for child in self.get_child_nodes(node):
if child in parents:
i = parents.index(child)
- self.circulars.append(parents[i:])
+ if parents[i:] not in self.circulars:
+ self.circulars.append(parents[i:])
else:
self.detect_circulars_sub(child, parents + [child])
@@ -266,7 +267,7 @@ class DiagramLayoutManager:
return False
- def set_node_width(self, depth=0):
+ def set_node_xpos(self, depth=0):
for node in self.diagram.nodes:
if node.xy.x != depth:
continue
@@ -283,7 +284,7 @@ class DiagramLayoutManager:
depther_node = [x for x in self.diagram.nodes if x.xy.x > depth]
if len(depther_node) > 0:
- self.set_node_width(depth + 1)
+ self.set_node_xpos(depth + 1)
def adjust_node_order(self):
for node in list(self.diagram.nodes):
@@ -380,7 +381,7 @@ class DiagramLayoutManager:
for h in range(height):
self.coordinates.append(XY(xy.x + w, xy.y + h))
- def set_node_height(self, node, height=0):
+ def set_node_ypos(self, node, height=0):
for x in range(node.colwidth):
for y in range(node.colheight):
xy = XY(node.xy.x + x, height + y)
@@ -406,7 +407,7 @@ class DiagramLayoutManager:
pass
else:
if isinstance(node, NodeGroup):
- parent_height = self.get_parent_node_height(node, child)
+ parent_height = self.get_parent_node_ypos(node, child)
if parent_height and parent_height > height:
height = parent_height
@@ -417,7 +418,7 @@ class DiagramLayoutManager:
height = max(coord) + 1
while True:
- if self.set_node_height(child, height):
+ if self.set_node_ypos(child, height):
child.xy = XY(child.xy.x, height)
self.mark_xy(child.xy, child.colwidth, child.colheight)
self.heightRefs.append(child.id)
@@ -455,7 +456,7 @@ class DiagramLayoutManager:
return ret
- def get_parent_node_height(self, parent, child):
+ def get_parent_node_ypos(self, parent, child):
heights = []
for e in DiagramEdge.find(parent, child):
y = parent.xy.y
diff --git a/src/blockdiag/command.py b/src/blockdiag/command.py
index a8c5e00..3d67a80 100644
--- a/src/blockdiag/command.py
+++ b/src/blockdiag/command.py
@@ -53,7 +53,8 @@ class BlockdiagApp(Application):
draw = DiagramDraw(self.options.type, group, outfile,
fontmap=self.fontmap,
antialias=self.options.antialias,
- nodoctype=self.options.nodoctype)
+ nodoctype=self.options.nodoctype,
+ transparency=self.options.transparency)
draw.draw()
draw.save()
diff --git a/src/blockdiag/drawer.py b/src/blockdiag/drawer.py
index 2ad6deb..5c3b6bd 100644
--- a/src/blockdiag/drawer.py
+++ b/src/blockdiag/drawer.py
@@ -49,7 +49,8 @@ class DiagramDraw(object):
self.shadow = kwargs.get('shadow', (0, 0, 0))
kwargs = dict(nodoctype=kwargs.get('nodoctype'),
- scale_ratio=self.scale_ratio)
+ scale_ratio=self.scale_ratio,
+ transparency=kwargs.get('transparency'))
drawer = imagedraw.create(self.format, self.filename,
self.pagesize(), **kwargs)
if drawer is None:
@@ -72,13 +73,10 @@ class DiagramDraw(object):
@property
def edges(self):
- for edge in (e for e in self.diagram.edges if e.style != 'none'):
+ edges = self.diagram.traverse_edges(preorder=True)
+ for edge in (e for e in edges if e.style != 'none'):
yield edge
- for group in self.groups:
- for edge in (e for e in group.edges if e.style != 'none'):
- yield edge
-
def pagesize(self, scaled=False):
if scaled:
metrics = self.metrics
diff --git a/src/blockdiag/elements.py b/src/blockdiag/elements.py
index 557c8f0..c0a0982 100644
--- a/src/blockdiag/elements.py
+++ b/src/blockdiag/elements.py
@@ -216,10 +216,9 @@ class DiagramNode(Element):
self.linecolor = images.color_to_rgb(color)
def set_shape(self, value):
- try:
- noderenderer.get(value)
+ if noderenderer.get(value):
self.shape = value
- except:
+ else:
msg = "WARNING: unknown node shape: %s\n" % value
raise AttributeError(msg)
@@ -308,6 +307,19 @@ class NodeGroup(Element):
else:
yield node
+ def traverse_edges(self, preorder=False):
+ if preorder:
+ for edge in self.edges:
+ yield edge
+
+ for group in self.traverse_groups(preorder):
+ for edge in group.traverse_edges(preorder):
+ yield edge
+
+ if not preorder:
+ for edge in self.edges:
+ yield edge
+
def traverse_groups(self, preorder=False):
for node in self.traverse_nodes(preorder=preorder):
if isinstance(node, NodeGroup):
@@ -438,6 +450,7 @@ class DiagramEdge(Base):
self.skipped = 0
self.label = None
+ self.description = None
self.dir = 'forward'
self.color = self.basecolor
self.hstyle = None
@@ -460,6 +473,15 @@ class DiagramEdge(Base):
value = value.lower()
if value in ('back', 'both', 'none', 'forward'):
self.dir = value
+ elif value == '-<':
+ self.dir = 'forward'
+ self.hstyle = 'onemany'
+ elif value == '>-':
+ self.dir = 'back'
+ self.hstyle = 'manyone'
+ elif value == '>-<':
+ self.dir = 'both'
+ self.hstyle = 'manymany'
elif value == '->':
self.dir = 'forward'
elif value == '<-':
@@ -479,6 +501,18 @@ class DiagramEdge(Base):
value = value.lower()
if value in ('generalization', 'composition', 'aggregation'):
self.hstyle = value
+ elif value == 'oneone':
+ self.dir = 'none'
+ self.hstyle = value
+ elif value == 'onemany':
+ self.dir = 'forward'
+ self.hstyle = value
+ elif value == 'manyone':
+ self.dir = 'back'
+ self.hstyle = value
+ elif value == 'manymany':
+ self.dir = 'both'
+ self.hstyle = value
else:
msg = "WARNING: unknown edge hstyle: %s\n" % value
raise AttributeError(msg)
@@ -521,6 +555,10 @@ class DiagramEdge(Base):
return dir
+ def to_desctable(self):
+ label = "%s -> %s" % (self.node1.label, self.node2.label)
+ return [label, self.description]
+
class Diagram(NodeGroup):
_DiagramNode = DiagramNode
@@ -562,10 +600,9 @@ class Diagram(NodeGroup):
plugins.load(modules, diagram=self)
def set_default_shape(self, value):
- try:
- noderenderer.get(value)
+ if noderenderer.get(value):
DiagramNode.set_default_shape(value)
- except:
+ else:
msg = "WARNING: unknown node shape: %s\n" % value
raise AttributeError(msg)
diff --git a/src/blockdiag/imagedraw/pdf.py b/src/blockdiag/imagedraw/pdf.py
index b6d7856..377ae08 100644
--- a/src/blockdiag/imagedraw/pdf.py
+++ b/src/blockdiag/imagedraw/pdf.py
@@ -149,10 +149,16 @@ class PDFImageDraw(object):
outline = kwargs.get('outline')
self.rectangle(lines.outlinebox, fill='white', outline=outline)
+ rendered = False
for string, xy in lines.lines:
self.text(xy, string, font, **kwargs)
+ rendered = True
self.canvas.restoreState()
+ if not rendered and font.size > 0:
+ font.size = int(font.size * 0.8)
+ self.textarea(box, string, font, **kwargs)
+
def line(self, xy, **kwargs):
self.set_stroke_color(kwargs.get('fill', 'none'))
self.set_style(kwargs.get('style'), kwargs.get('thick'))
diff --git a/src/blockdiag/imagedraw/png.py b/src/blockdiag/imagedraw/png.py
index c87dd35..0624e5a 100644
--- a/src/blockdiag/imagedraw/png.py
+++ b/src/blockdiag/imagedraw/png.py
@@ -111,8 +111,9 @@ class ImageDrawEx(object):
self.image = Image.new('RGB', size, (256, 256, 256))
# set transparency to background
- alpha = Image.new('L', size, 1)
- self.image.putalpha(alpha)
+ if kwargs.get('transparency'):
+ alpha = Image.new('L', size, 1)
+ self.image.putalpha(alpha)
self.filename = filename
self.scale_ratio = kwargs.get('scale_ratio', 1)
@@ -298,7 +299,8 @@ class ImageDrawEx(object):
else:
_box = box
- text = ImageDrawEx(None, _box.size, parent=self, mode=self.mode)
+ text = ImageDrawEx(None, _box.size, parent=self, mode=self.mode,
+ transparency=True)
textbox = (0, 0, _box.width, _box.height)
text.textarea(textbox, string, font, **kwargs)
@@ -313,8 +315,14 @@ class ImageDrawEx(object):
outline = kwargs.get('outline')
self.rectangle(lines.outlinebox, fill='white', outline=outline)
+ rendered = False
for string, xy in lines.lines:
self.text(xy, string, font, **kwargs)
+ rendered = True
+
+ if not rendered and font.size > 0:
+ font.size = int(font.size * 0.8)
+ self.textarea(box, string, font, **kwargs)
def loadImage(self, filename, box):
box_width = box[2] - box[0]
diff --git a/src/blockdiag/imagedraw/svg.py b/src/blockdiag/imagedraw/svg.py
index 86c608d..122dea3 100644
--- a/src/blockdiag/imagedraw/svg.py
+++ b/src/blockdiag/imagedraw/svg.py
@@ -137,8 +137,14 @@ class SVGImageDrawElement(object):
outline = kwargs.get('outline')
self.rectangle(lines.outlinebox, fill='white', outline=outline)
+ rendered = False
for string, xy in lines.lines:
self.text(xy, string, font, **kwargs)
+ rendered = True
+
+ if not rendered and font.size > 0:
+ font.size = int(font.size * 0.8)
+ self.textarea(box, string, font, **kwargs)
def line(self, xy, **kwargs):
fill = kwargs.get('fill')
diff --git a/src/blockdiag/metrics.py b/src/blockdiag/metrics.py
index 8f5d86b..7563cc7 100644
--- a/src/blockdiag/metrics.py
+++ b/src/blockdiag/metrics.py
@@ -425,6 +425,34 @@ class EdgeMetrics(object):
head.append(XY(xy.x + cell * 2, xy.y))
head.append(XY(xy.x + cell, xy.y + cell / 2))
head.append(XY(xy.x + 1, xy.y))
+ elif direct == 'rup':
+ xy = node.bottom
+ head.append(XY(xy.x, xy.y + cell))
+ head.append(XY(xy.x - cell, xy.y + 1))
+ head.append(XY(xy.x, xy.y + 1 * 2))
+ head.append(XY(xy.x + cell, xy.y + 1))
+ head.append(XY(xy.x, xy.y + cell))
+ elif direct == 'rdown':
+ xy = node.top
+ head.append(XY(xy.x, xy.y - cell))
+ head.append(XY(xy.x - cell, xy.y - 1))
+ head.append(XY(xy.x, xy.y - 1 * 2))
+ head.append(XY(xy.x + cell, xy.y - 1))
+ head.append(XY(xy.x, xy.y - cell))
+ elif direct == 'rright':
+ xy = node.left
+ head.append(XY(xy.x - cell, xy.y))
+ head.append(XY(xy.x - 1, xy.y - cell))
+ head.append(XY(xy.x - 1 * 2, xy.y))
+ head.append(XY(xy.x - 1, xy.y + cell))
+ head.append(XY(xy.x - cell, xy.y))
+ elif direct == 'rleft':
+ xy = node.right
+ head.append(XY(xy.x + cell, xy.y))
+ head.append(XY(xy.x + 1, xy.y - cell))
+ head.append(XY(xy.x + 1 * 2, xy.y))
+ head.append(XY(xy.x + 1, xy.y + cell))
+ head.append(XY(xy.x + cell, xy.y))
if self.edge.hstyle not in ('composition', 'aggregation'):
head.pop(2)
@@ -447,6 +475,14 @@ class EdgeMetrics(object):
lines.polylines[0].insert(0, XY(pt.x + cell, pt.y))
elif head1 == 'down':
lines.polylines[0].insert(0, XY(pt.x, pt.y - cell))
+ elif head1 == 'rup':
+ lines.polylines[0].insert(0, XY(pt.x, pt.y + cell))
+ elif head1 == 'rright':
+ lines.polylines[0].insert(0, XY(pt.x - cell, pt.y))
+ elif head1 == 'rleft':
+ lines.polylines[0].insert(0, XY(pt.x + cell, pt.y))
+ elif head1 == 'rdown':
+ lines.polylines[0].insert(0, XY(pt.x, pt.y - cell))
if head2:
pt = lines.polylines[-1].pop()
@@ -458,6 +494,14 @@ class EdgeMetrics(object):
lines.polylines[-1].append(XY(pt.x + cell, pt.y))
elif head2 == 'down':
lines.polylines[-1].append(XY(pt.x, pt.y - cell))
+ elif head2 == 'rup':
+ lines.polylines[-1].append(XY(pt.x, pt.y + cell))
+ elif head2 == 'rright':
+ lines.polylines[-1].append(XY(pt.x - cell, pt.y))
+ elif head2 == 'rleft':
+ lines.polylines[-1].append(XY(pt.x + cell, pt.y))
+ elif head2 == 'rdown':
+ lines.polylines[-1].append(XY(pt.x, pt.y - cell))
return lines
@@ -486,6 +530,9 @@ class LandscapeEdgeMetrics(EdgeMetrics):
heads.append('left')
else:
heads.append('up')
+
+ if self.edge.hstyle in ('manyone', 'manymany'):
+ heads[-1] = 'r' + heads[-1]
else:
heads.append(None)
@@ -496,6 +543,9 @@ class LandscapeEdgeMetrics(EdgeMetrics):
heads.append('up')
elif dir in ('left-up', 'left', 'left-down', 'down', 'same'):
heads.append('down')
+
+ if self.edge.hstyle in ('onemany', 'manymany'):
+ heads[-1] = 'r' + heads[-1]
else:
heads.append(None)
@@ -680,6 +730,9 @@ class PortraitEdgeMetrics(EdgeMetrics):
heads.append('left')
else:
heads.append('up')
+
+ if self.edge.hstyle in ('manyone', 'manymany'):
+ heads[-1] = 'r' + heads[-1]
else:
heads.append(None)
@@ -693,6 +746,9 @@ class PortraitEdgeMetrics(EdgeMetrics):
heads.append('down')
elif dir in ('left-up', 'left', 'left-down', 'down', 'right-down'):
heads.append('down')
+
+ if self.edge.hstyle in ('onemany', 'manymany'):
+ heads[-1] = 'r' + heads[-1]
else:
heads.append(None)
@@ -840,12 +896,18 @@ class FlowchartLandscapeEdgeMetrics(LandscapeEdgeMetrics):
if self.edge.direction == 'right-down':
if self.edge.dir in ('back', 'both'):
- heads.append('up')
+ if self.edge.hstyle in ('manyone', 'manymany'):
+ heads.append('rup')
+ else:
+ heads.append('up')
else:
heads.append(None)
if self.edge.dir in ('forward', 'both'):
- heads.append('right')
+ if self.edge.hstyle in ('onemany', 'manymany'):
+ heads.append('rright')
+ else:
+ heads.append('right')
else:
heads.append(None)
else:
@@ -909,12 +971,18 @@ class FlowchartPortraitEdgeMetrics(PortraitEdgeMetrics):
if self.edge.direction == 'right-down':
if self.edge.dir in ('back', 'both'):
- heads.append('left')
+ if self.edge.hstyle in ('manyone', 'manymany'):
+ heads.append('left')
+ else:
+ heads.append('left')
else:
heads.append(None)
if self.edge.dir in ('forward', 'both'):
- heads.append('down')
+ if self.edge.dir in ('onemany', 'manymany'):
+ heads.append('rdown')
+ else:
+ heads.append('down')
else:
heads.append(None)
else:
diff --git a/src/blockdiag/noderenderer/__init__.py b/src/blockdiag/noderenderer/__init__.py
index ad3d3b2..0165c21 100644
--- a/src/blockdiag/noderenderer/__init__.py
+++ b/src/blockdiag/noderenderer/__init__.py
@@ -46,7 +46,7 @@ def get(shape):
if name in renderers:
return renderers[name]
- return renderers[shape]
+ return renderers.get(shape)
class NodeShape(object):
diff --git a/src/blockdiag/noderenderer/actor.py b/src/blockdiag/noderenderer/actor.py
index cae08b6..d1ada53 100644
--- a/src/blockdiag/noderenderer/actor.py
+++ b/src/blockdiag/noderenderer/actor.py
@@ -24,18 +24,18 @@ class Actor(NodeShape):
shortside = min(self.node.width or metrics.node_height,
self.node.height or metrics.node_height)
- self.radius = shortside / 8 # radius of actor's head
+ r = self.radius = shortside / 8 # radius of actor's head
self.center = metrics.cell(node).center
- self.connectors[0] = XY(self.center.x, self.center.y - self.radius * 4)
- self.connectors[1] = XY(self.center.x + self.radius * 4, self.center.y)
- self.connectors[2] = XY(self.center.x, self.center.y + self.radius * 4)
- self.connectors[3] = XY(self.center.x - self.radius * 4, self.center.y)
+ self.connectors[0] = XY(self.center.x, self.center.y - r * 9 / 2)
+ self.connectors[1] = XY(self.center.x + r * 4, self.center.y)
+ self.connectors[2] = XY(self.center.x, self.center.y + r * 4)
+ self.connectors[3] = XY(self.center.x - r * 4, self.center.y)
def head_part(self):
- r = self.radius
- pt = self.metrics.cell(self.node).center
- return Box(pt.x - r, pt.y - r * 4, pt.x + r, pt.y - r * 2)
+ r = self.radius * 3 / 2
+ pt = self.metrics.cell(self.node).center.shift(y=-self.radius * 3)
+ return Box(pt.x - r, pt.y - r, pt.x + r, pt.y + r)
def body_part(self):
r = self.radius
diff --git a/src/blockdiag/parser.py b/src/blockdiag/parser.py
index 34a85f7..e9d57d0 100644
--- a/src/blockdiag/parser.py
+++ b/src/blockdiag/parser.py
@@ -69,7 +69,7 @@ def tokenize(str):
('Space', (r'[ \t\r\n]+',)),
('Name', (ur'[A-Za-z_0-9\u0080-\uffff]'
ur'[A-Za-z_\-.0-9\u0080-\uffff]*',)),
- ('Op', (r'[{};,=\[\]]|(<->)|(<-)|(--)|(->)',)),
+ ('Op', (r'[{};,=\[\]]|(<->)|(<-)|(--)|(->)|(>-<)|(-<)|(>-)',)),
('Number', (r'-?(\.[0-9]+)|([0-9]+(\.[0-9]*)?)',)),
('String', (r'(?P<quote>"|\').*?(?<!\\)(?P=quote)', DOTALL)),
]
@@ -111,7 +111,8 @@ def parse(seq):
# We use a forward_decl becaue of circular definitions like (stmt_list ->
# stmt -> group -> stmt_list)
group = forward_decl()
- edge_rhs = (op('->') | op('--') | op('<-') | op('<->')) + node_list
+ edge_rhs = (op('->') | op('--') | op('<-') | op('<->') |
+ op('>-') | op('-<') | op('>-<')) + node_list
edge_stmt = (
node_list +
edge_rhs +
diff --git a/src/blockdiag/tests/diagrams/circular_ref2.diag b/src/blockdiag/tests/diagrams/circular_ref2.diag
new file mode 100644
index 0000000..8e8115b
--- /dev/null
+++ b/src/blockdiag/tests/diagrams/circular_ref2.diag
@@ -0,0 +1,4 @@
+{
+ A -> B -> C -> D, E -> F -> C;
+ Z;
+}
diff --git a/src/blockdiag/tests/diagrams/edge_datamodels.diag b/src/blockdiag/tests/diagrams/edge_datamodels.diag
new file mode 100644
index 0000000..a1dff47
--- /dev/null
+++ b/src/blockdiag/tests/diagrams/edge_datamodels.diag
@@ -0,0 +1,3 @@
+{
+ A >- B >-< C -< D;
+}
diff --git a/src/blockdiag/tests/test_boot_params.py b/src/blockdiag/tests/test_boot_params.py
index 1555fee..a4b1053 100644
--- a/src/blockdiag/tests/test_boot_params.py
+++ b/src/blockdiag/tests/test_boot_params.py
@@ -65,6 +65,23 @@ class TestBootParams(unittest2.TestCase):
sys.argv = ['', '-Tpdf', '--nodoctype', 'input.diag']
self.parser.parse()
+ @assertRaises(RuntimeError)
+ @argv_wrapper
+ def test_svg_notransparency_option(self):
+ sys.argv = ['', '-Tsvg', '--no-transparency', 'input.diag']
+ self.parser.parse()
+
+ @argv_wrapper
+ def test_png_notransparency_option(self):
+ sys.argv = ['', '-Tpng', '--no-transparency', 'input.diag']
+ self.parser.parse()
+
+ @assertRaises(RuntimeError)
+ @argv_wrapper
+ def test_pdf_notransparency_option(self):
+ sys.argv = ['', '-Tpdf', '--no-transparency', 'input.diag']
+ self.parser.parse()
+
@argv_wrapper
def test_config_option(self):
try:
diff --git a/src/blockdiag/tests/test_builder.py b/src/blockdiag/tests/test_builder.py
index 3608cc8..d96942a 100644
--- a/src/blockdiag/tests/test_builder.py
+++ b/src/blockdiag/tests/test_builder.py
@@ -34,16 +34,22 @@ def test_diagram_attributes_order_diagram():
def test_circular_ref_to_root_diagram():
positions = {'A': (0, 0), 'B': (1, 0), 'C': (2, 0),
- 'D': (2, 1), 'Z': (0, 2)}
+ 'D': (2, 1), 'Z': (0, 2)}
__validate_node_attributes('circular_ref_to_root.diag', xy=positions)
def test_circular_ref_diagram():
positions = {'A': (0, 0), 'B': (1, 0), 'C': (2, 0),
- 'D': (2, 1), 'Z': (0, 2)}
+ 'D': (2, 1), 'Z': (0, 2)}
__validate_node_attributes('circular_ref.diag', xy=positions)
+def test_circular_ref2_diagram():
+ positions = {'A': (0, 0), 'B': (1, 0), 'C': (2, 0), 'D': (3, 0),
+ 'E': (3, 1), 'F': (4, 0), 'Z': (0, 2)}
+ __validate_node_attributes('circular_ref2.diag', xy=positions)
+
+
def test_circular_ref_and_parent_node_diagram():
positions = {'A': (0, 0), 'B': (1, 0), 'C': (1, 1),
'D': (2, 1), 'Z': (0, 2)}
@@ -59,7 +65,7 @@ def test_labeled_circular_ref_diagram():
def test_twin_forked_diagram():
positions = {'A': (0, 0), 'B': (1, 0), 'C': (1, 2), 'D': (2, 0),
- 'E': (3, 0), 'F': (3, 1), 'G': (4, 1), 'Z': (0, 3)}
+ 'E': (3, 0), 'F': (3, 1), 'G': (4, 1), 'Z': (0, 3)}
__validate_node_attributes('twin_forked.diag', xy=positions)
diff --git a/src/blockdiag/tests/test_rst_directives.py b/src/blockdiag/tests/test_rst_directives.py
index 73b9783..dcdb205 100644
--- a/src/blockdiag/tests/test_rst_directives.py
+++ b/src/blockdiag/tests/test_rst_directives.py
@@ -232,6 +232,61 @@ class TestRstDirectives(unittest2.TestCase):
self.assertEqual(0, len(tbody[1][1]))
@use_tmpdir
+ def test_rst_directives_with_block_desctable_using_node_group(self, path):
+ directives.setup(format='SVG', outputdir=path)
+ text = ".. blockdiag::\n :desctable:\n\n { A -> B; group { A } }"
+ doctree = publish_doctree(text)
+ self.assertEqual(2, len(doctree))
+ self.assertEqual(nodes.image, type(doctree[0]))
+ self.assertEqual(nodes.table, type(doctree[1]))
+
+ self.assertEqual(1, len(doctree[1]))
+ self.assertEqual(nodes.tgroup, type(doctree[1][0]))
+
+ # tgroup
+ self.assertEqual(4, len(doctree[1][0]))
+ self.assertEqual(nodes.colspec, type(doctree[1][0][0]))
+ self.assertEqual(nodes.colspec, type(doctree[1][0][1]))
+ self.assertEqual(nodes.thead, type(doctree[1][0][2]))
+ self.assertEqual(nodes.tbody, type(doctree[1][0][3]))
+
+ # colspec
+ self.assertEqual(0, len(doctree[1][0][0]))
+ self.assertEqual(50, doctree[1][0][0]['colwidth'])
+
+ self.assertEqual(0, len(doctree[1][0][1]))
+ self.assertEqual(50, doctree[1][0][1]['colwidth'])
+
+ # thead
+ thead = doctree[1][0][2]
+ self.assertEqual(1, len(thead))
+ self.assertEqual(2, len(thead[0]))
+
+ self.assertEqual(1, len(thead[0][0]))
+ self.assertEqual(1, len(thead[0][0][0]))
+ self.assertEqual('Name', thead[0][0][0][0])
+
+ self.assertEqual(1, len(thead[0][1]))
+ self.assertEqual(1, len(thead[0][1][0]))
+ self.assertEqual('Description', thead[0][1][0][0])
+
+ # tbody
+ tbody = doctree[1][0][3]
+ self.assertEqual(2, len(tbody))
+
+ self.assertEqual(2, len(tbody[0]))
+ self.assertEqual(1, len(tbody[0][0]))
+ self.assertEqual(1, len(tbody[0][0][0]))
+ self.assertEqual('A', tbody[0][0][0][0])
+ self.assertEqual(0, len(tbody[0][1]))
+
+ self.assertEqual(2, len(tbody[1]))
+ self.assertEqual(1, len(tbody[1][0]))
+ self.assertEqual(1, len(tbody[1][0][0]))
+ self.assertEqual('B', tbody[1][0][0][0])
+ self.assertEqual(0, len(tbody[1][1]))
+
+ @use_tmpdir
def test_rst_directives_with_block_desctable_with_description(self, path):
directives.setup(format='SVG', outputdir=path)
text = ".. blockdiag::\n :desctable:\n\n" + \
@@ -312,7 +367,6 @@ class TestRstDirectives(unittest2.TestCase):
self.assertEqual('B', tbody[1][0][0][0])
self.assertEqual(4, len(tbody[1][1][0]))
- print tbody[1][1][0]
self.assertEqual(nodes.strong, type(tbody[1][1][0][0]))
self.assertEqual(nodes.Text, type(tbody[1][1][0][0][0]))
self.assertEqual('foo', str(tbody[1][1][0][0][0]))
@@ -363,3 +417,46 @@ class TestRstDirectives(unittest2.TestCase):
self.assertEqual('2', tbody[1][0][0][0])
self.assertEqual('A', tbody[1][1][0][0])
self.assertEqual(0, len(tbody[1][2]))
+
+ @use_tmpdir
+ def test_rst_directives_with_block_desctable_for_edges(self, path):
+ directives.setup(format='SVG', outputdir=path)
+ text = ".. blockdiag::\n :desctable:\n\n" + \
+ " { A -> B [description = \"foo\"]; " + \
+ " C -> D [description = \"bar\"]; " + \
+ " C [label = \"label_C\"]; " + \
+ " D [label = \"label_D\"]; }"
+ doctree = publish_doctree(text)
+ self.assertEqual(3, len(doctree))
+ self.assertEqual(nodes.image, type(doctree[0]))
+ self.assertEqual(nodes.table, type(doctree[1]))
+ self.assertEqual(nodes.table, type(doctree[2]))
+
+ # tgroup
+ self.assertEqual(4, len(doctree[2][0]))
+ self.assertEqual(nodes.colspec, type(doctree[2][0][0]))
+ self.assertEqual(nodes.colspec, type(doctree[2][0][1]))
+ self.assertEqual(nodes.thead, type(doctree[2][0][2]))
+ self.assertEqual(nodes.tbody, type(doctree[2][0][3]))
+
+ # colspec
+ self.assertEqual(25, doctree[2][0][0]['colwidth'])
+ self.assertEqual(50, doctree[2][0][1]['colwidth'])
+
+ # thead
+ thead = doctree[2][0][2]
+ self.assertEqual(2, len(thead[0]))
+ self.assertEqual('Name', thead[0][0][0][0])
+ self.assertEqual('Description', thead[0][1][0][0])
+
+ # tbody
+ tbody = doctree[2][0][3]
+ self.assertEqual(2, len(tbody))
+ self.assertEqual('A -> B', tbody[0][0][0][0])
+ self.assertEqual(1, len(tbody[0][1][0]))
+ self.assertEqual(nodes.Text, type(tbody[0][1][0][0]))
+ self.assertEqual('foo', str(tbody[0][1][0][0]))
+ self.assertEqual('label_C -> label_D', tbody[1][0][0][0])
+ self.assertEqual(1, len(tbody[1][1][0]))
+ self.assertEqual(nodes.Text, type(tbody[1][1][0][0]))
+ self.assertEqual('bar', str(tbody[1][1][0][0]))
diff --git a/src/blockdiag/utils/bootstrap.py b/src/blockdiag/utils/bootstrap.py
index 2856308..0a0a2fc 100644
--- a/src/blockdiag/utils/bootstrap.py
+++ b/src/blockdiag/utils/bootstrap.py
@@ -31,6 +31,8 @@ class Application(object):
parsed = self.parse_diagram()
return self.build_diagram(parsed)
+ except SystemExit, e:
+ return e
except UnicodeEncodeError, e:
msg = "ERROR: UnicodeEncodeError caught " + \
"(check your font settings)\n"
@@ -64,7 +66,8 @@ class Application(object):
drawer = DiagramDraw(self.options.type, diagram,
self.options.output, fontmap=self.fontmap,
antialias=self.options.antialias,
- nodoctype=self.options.nodoctype)
+ nodoctype=self.options.nodoctype,
+ transparency=self.options.transparency)
drawer.draw()
drawer.save()
@@ -97,6 +100,10 @@ class Options(object):
help='use FONT to draw diagram', metavar='FONT')
p.add_option('--fontmap',
help='use FONTMAP file to draw diagram', metavar='FONT')
+ p.add_option('--no-transparency', dest='transparency',
+ default=True, action='store_false',
+ help='do not make transparent background of diagram ' +\
+ '(PNG only)')
p.add_option('-T', dest='type', default='PNG',
help='Output diagram as TYPE format')
p.add_option('--nodoctype', action='store_true',
@@ -134,6 +141,10 @@ class Options(object):
msg = "--nodoctype option work in SVG images."
raise RuntimeError(msg)
+ if self.options.transparency is False and self.options.type != 'PNG':
+ msg = "--no-transparency option work in PNG images."
+ raise RuntimeError(msg)
+
if self.options.config and not os.path.isfile(self.options.config):
msg = "config file is not found: %s" % self.options.config
raise RuntimeError(msg)
diff --git a/src/blockdiag/utils/rst/directives.py b/src/blockdiag/utils/rst/directives.py
index 707ca0a..07d4440 100644
--- a/src/blockdiag/utils/rst/directives.py
+++ b/src/blockdiag/utils/rst/directives.py
@@ -132,7 +132,7 @@ class BlockdiagDirective(BlockdiagDirectiveBase):
if 'desctable' in node['options']:
del node['options']['desctable']
- results.append(self.description_table(diagram))
+ results += self.description_tables(diagram)
results[0] = self.node2image(node, diagram)
@@ -201,14 +201,26 @@ class BlockdiagDirective(BlockdiagDirectiveBase):
return filename
- def description_table(self, diagram):
- nodes = diagram.traverse_nodes
+ def description_tables(self, diagram):
+ tables = []
+ desctable = self.node_description_table(diagram)
+ if desctable:
+ tables.append(desctable)
+
+ desctable = self.edge_description_table(diagram)
+ if desctable:
+ tables.append(desctable)
+
+ return tables
+
+ def node_description_table(self, diagram):
+ nodes = diagram.traverse_nodes()
klass = diagram._DiagramNode
widths = [25] + [50] * (len(klass.desctable) - 1)
headers = [klass.attrname[n] for n in klass.desctable]
- descriptions = [n.to_desctable() for n in nodes()]
+ descriptions = [n.to_desctable() for n in nodes if n.drawable]
descriptions.sort(cmp_node_number)
for i in range(len(headers) - 2, -1, -1):
@@ -222,6 +234,18 @@ class BlockdiagDirective(BlockdiagDirectiveBase):
return self._description_table(descriptions, widths, headers)
+ def edge_description_table(self, diagram):
+ edges = diagram.traverse_edges()
+
+ widths = [25, 50]
+ headers = ['Name', 'Description']
+ descriptions = [e.to_desctable() for e in edges if e.style != 'none']
+
+ if any(desc[1] for desc in descriptions):
+ return self._description_table(descriptions, widths, headers)
+ else:
+ return None
+
def _description_table(self, descriptions, widths, headers):
# generate table-root
tgroup = nodes.tgroup(cols=len(widths))
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/blockdiag.git
More information about the debian-science-commits
mailing list