Skip to content

Commit

Permalink
Simplify the dependency graph generation, by relying on dot to genera…
Browse files Browse the repository at this point in the history
…te PDF (and

now also SVG) directly. Default to showing SVG from the link on a group's page.
Commit ready for merge.
 - Legacy-Id: 10623
  • Loading branch information
larseggert committed Dec 22, 2015
1 parent b23952c commit f1dcfca
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 40 deletions.
56 changes: 26 additions & 30 deletions ietf/group/info.py
Expand Up @@ -336,7 +336,9 @@ def construct_group_menu_context(request, group, selected, group_type, others):
entries.append(("Email expansions", urlreverse("ietf.group.info.email", kwargs=kwargs)))
entries.append(("History", urlreverse("ietf.group.info.history", kwargs=kwargs)))
if group.features.has_documents:
entries.append((mark_safe("Dependency graph »"), urlreverse("ietf.group.info.dependencies_pdf", kwargs=kwargs)))
kwargs["output_type"] = "svg"
entries.append((mark_safe("Dependency graph »"), urlreverse("ietf.group.info.dependencies", kwargs=kwargs)))
del kwargs["output_type"]

if group.list_archive.startswith("http:") or group.list_archive.startswith("https:") or group.list_archive.startswith("ftp:"):
entries.append((mark_safe("List archive »"), group.list_archive))
Expand Down Expand Up @@ -656,50 +658,44 @@ def make_dot(group):
dict( nodes=nodes, edges=edges )
)

def dependencies_dot(request, acronym, group_type=None):
@cache_page(60 * 60)
def dependencies(request, acronym, group_type=None, output_type="pdf"):
group = get_group_or_404(acronym, group_type)
if not group.features.has_documents:
raise Http404

return HttpResponse(make_dot(group),
content_type='text/plain; charset=UTF-8'
)

@cache_page ( 60 * 60 )
def dependencies_pdf(request, acronym, group_type=None):
group = get_group_or_404(acronym, group_type)
if not group.features.has_documents:
raise Http404

dothandle,dotname = mkstemp()
dothandle, dotname = mkstemp()
os.close(dothandle)
dotfile = open(dotname,"w")
dotfile = open(dotname, "w")
dotfile.write(make_dot(group))
dotfile.close()

unflathandle,unflatname = mkstemp()
os.close(unflathandle)
if (output_type == "dot"):
return HttpResponse(make_dot(group),
content_type='text/plain; charset=UTF-8'
)

pshandle,psname = mkstemp()
os.close(pshandle)
unflathandle, unflatname = mkstemp()
os.close(unflathandle)
outhandle, outname = mkstemp()
os.close(outhandle)

pdfhandle,pdfname = mkstemp()
os.close(pdfhandle)
pipe("%s -f -l 10 -o %s %s" % (settings.UNFLATTEN_BINARY, unflatname, dotname))
pipe("%s -T%s -o %s %s" % (settings.DOT_BINARY, output_type, outname, unflatname))

pipe("%s -f -l 10 -o %s %s" % (settings.UNFLATTEN_BINARY,unflatname,dotname))
pipe("%s -Tps -Gsize=10.5,8.0 -Gmargin=0.25 -Gratio=auto -Grotate=90 -o %s %s" % (settings.DOT_BINARY,psname,unflatname))
pipe("%s %s %s" % (settings.PS2PDF_BINARY,psname,pdfname))

pdfhandle = open(pdfname,"r")
pdf = pdfhandle.read()
pdfhandle.close()
outhandle = open(outname, "r")
out = outhandle.read()
outhandle.close()

os.unlink(pdfname)
os.unlink(psname)
os.unlink(outname)
os.unlink(unflatname)
os.unlink(dotname)

return HttpResponse(pdf, content_type='application/pdf')
if (output_type == "pdf"):
output_type = "application/pdf"
elif (output_type == "svg"):
output_type = "image/svg+xml"
return HttpResponse(out, content_type=output_type)

def email_aliases(request, acronym=None, group_type=None):
group = get_group_or_404(acronym,group_type) if acronym else None
Expand Down
26 changes: 19 additions & 7 deletions ietf/group/tests.py
Expand Up @@ -14,8 +14,7 @@
skip_dot_to_pdf = True
skip_message = "settings.SKIP_DOT_TO_PDF = %s" % skip_dot_to_pdf
elif ( os.path.exists(settings.DOT_BINARY) and
os.path.exists(settings.UNFLATTEN_BINARY) and
os.path.exists(settings.PS2PDF_BINARY)):
os.path.exists(settings.UNFLATTEN_BINARY)):
skip_dot_to_pdf = False
skip_message = ""
else:
Expand Down Expand Up @@ -62,9 +61,9 @@ class GroupTests(TestCase):
def test_group_document_dependency_dotfile(self):
make_test_data()
for group in Group.objects.filter(Q(type="wg") | Q(type="rg")):
client = Client(Accept='application/pdf')
for url in [ urlreverse("ietf.group.info.dependencies_dot",kwargs=dict(acronym=group.acronym)),
urlreverse("ietf.group.info.dependencies_dot",kwargs=dict(acronym=group.acronym,group_type=group.type_id)),
client = Client(Accept='text/plain')
for url in [ urlreverse("ietf.group.info.dependencies",kwargs=dict(acronym=group.acronym,output_type="dot")),
urlreverse("ietf.group.info.dependencies",kwargs=dict(acronym=group.acronym,group_type=group.type_id,output_type="dot")),
]:
r = client.get(url)
self.assertTrue(r.status_code == 200, "Failed to receive "
Expand All @@ -76,12 +75,25 @@ def test_group_document_dependency_pdffile(self):
make_test_data()
for group in Group.objects.filter(Q(type="wg") | Q(type="rg")):
client = Client(Accept='application/pdf')
for url in [ urlreverse("ietf.group.info.dependencies_pdf",kwargs=dict(acronym=group.acronym)),
urlreverse("ietf.group.info.dependencies_pdf",kwargs=dict(acronym=group.acronym,group_type=group.type_id)),
for url in [ urlreverse("ietf.group.info.dependencies",kwargs=dict(acronym=group.acronym,output_type="pdf")),
urlreverse("ietf.group.info.dependencies",kwargs=dict(acronym=group.acronym,group_type=group.type_id,output_type="pdf")),
]:
r = client.get(url)
self.assertTrue(r.status_code == 200, "Failed to receive "
"a pdf dependency graph for group: %s"%group.acronym)
self.assertGreater(len(r.content), 0, "Pdf dependency graph for group "
"%s has no content"%group.acronym)

def test_group_document_dependency_svgfile(self):
make_test_data()
for group in Group.objects.filter(Q(type="wg") | Q(type="rg")):
client = Client(Accept='image/svg+xml')
for url in [ urlreverse("ietf.group.info.dependencies",kwargs=dict(acronym=group.acronym,output_type="svg")),
urlreverse("ietf.group.info.dependencies",kwargs=dict(acronym=group.acronym,group_type=group.type_id,output_type="svg")),
]:
r = client.get(url)
self.assertTrue(r.status_code == 200, "Failed to receive "
"a svg dependency graph for group: %s"%group.acronym)
self.assertGreater(len(r.content), 0, "svg dependency graph for group "
"%s has no content"%group.acronym)

3 changes: 1 addition & 2 deletions ietf/group/urls_info_details.py
Expand Up @@ -9,8 +9,7 @@
(r'^about/$', 'ietf.group.info.group_about', None, 'group_about'),
(r'^history/$','ietf.group.info.history'),
(r'^email/$', 'ietf.group.info.email'),
(r'^deps/dot/$', 'ietf.group.info.dependencies_dot'),
(r'^deps/pdf/$', 'ietf.group.info.dependencies_pdf'),
(r'^deps/(?P<output_type>[\w-]+)/$', 'ietf.group.info.dependencies'),
(r'^init-charter/', 'ietf.group.edit.submit_initial_charter'),
(r'^edit/$', 'ietf.group.edit.edit', {'action': "edit"}, "group_edit"),
(r'^conclude/$', 'ietf.group.edit.conclude'),
Expand Down
1 change: 0 additions & 1 deletion ietf/settings.py
Expand Up @@ -506,7 +506,6 @@ def skip_unreadable_post(record):

DOT_BINARY = '/usr/bin/dot'
UNFLATTEN_BINARY= '/usr/bin/unflatten'
PS2PDF_BINARY = '/usr/bin/ps2pdf'
RSYNC_BINARY = '/usr/bin/rsync'

# Account settings
Expand Down

0 comments on commit f1dcfca

Please sign in to comment.