# Based on original code, Copyright 2004 Toby Dickenson,
# with changes 2014 (c) Bjorn Pettersen
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject
# to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from .render_context import RenderBuffer
from . import colors
[docs]
class PyDepGraphDot(object):
def __init__(self, **kw):
self.kw = kw
[docs]
def render(self, depgraph, ctx):
with ctx.graph():
visited = set()
drawn = set()
for aname, bname in depgraph.cyclerelations:
try:
a = depgraph.sources[aname]
b = depgraph.sources[bname]
except KeyError:
continue
drawn.add((bname, aname))
ctx.write_rule(
aname, bname,
weight=depgraph.proximity_metric(a, b),
minlen=depgraph.dissimilarity_metric(a, b),
)
for a, b in sorted(depgraph):
# b imports a
aname = a.name
bname = b.name
if (bname, aname) in drawn:
continue
drawn.add((bname, aname))
ctx.write_rule(
aname, bname,
weight=depgraph.proximity_metric(a, b),
minlen=depgraph.dissimilarity_metric(a, b))
visited.add(a)
visited.add(b)
space = colors.ColorSpace(visited)
for src in sorted(visited):
bg, fg = depgraph.get_colors(src, space)
kwargs = {}
if src.name in depgraph.cyclenodes:
kwargs['shape'] = 'octagon'
ctx.write_node(
src.name,
label=src.get_label(splitlength=14,
rmprefix=self.kw.get('rmprefix')),
fillcolor=colors.rgb2css(bg),
fontcolor=colors.rgb2css(fg),
**kwargs
)
return ctx.text()
[docs]
class CycleGraphDot(object):
def __init__(self, **kw):
self.kw = kw
[docs]
def render(self, depgraph, ctx):
with ctx.graph(concentrate=False):
visited = set()
drawn = set()
relations = set()
for aname, bname in sorted(depgraph.cyclerelations):
try:
a = depgraph.sources[aname]
b = depgraph.sources[bname]
except KeyError:
continue
drawn.add((bname, aname))
ctx.write_rule(
bname, aname,
# weight=depgraph.proximity_metric(a, b),
# minlen=depgraph.dissimilarity_metric(a, b),
)
relations.add(aname)
relations.add(bname)
visited.add(a)
visited.add(b)
space = colors.ColorSpace(visited)
for src in sorted(visited, key=lambda x: x.name.lower()):
# if src.name not in relations:
# print('skipping', src.name)
# continue
bg, fg = depgraph.get_colors(src, space)
kwargs = {}
if src.name in depgraph.cyclenodes:
kwargs['shape'] = 'octagon'
ctx.write_node(
src.name, label=src.label,
fillcolor=colors.rgb2css(bg),
fontcolor=colors.rgb2css(fg),
**kwargs
)
return ctx.text()
[docs]
def dep2dot(target, depgraph, **kw):
dotter = PyDepGraphDot(**kw)
ctx = RenderBuffer(target, **kw)
return dotter.render(depgraph, ctx)
[docs]
def cycles2dot(target, depgraph, **kw):
dotter = CycleGraphDot(**kw)
ctx = RenderBuffer(target, remove_islands=False, **kw)
return dotter.render(depgraph, ctx)