Attachment 'GraphViz.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 GraphViz parser module for MoinMoin
4
5 ----
6 Copyright (C) 2007 Zoran Isailovski
7 Copyright (C) 2008 Remco Boerma
8 Licensed under the Apache License, Version 2.0 (see http://www.apache.org/licenses/LICENSE-2.0)
9 or, at your option, under the terms described in the file LICENSE.txt found in the root of the
10 distribution of this package (as far as it denotes a different license then the above).
11 """
12 import os.path
13 import sha
14 import re
15 from MoinMoin.parser import text_moin_wiki
16 from MoinMoin import wikiutil
17 from MoinMoin.action import AttachFile
18
19 VALID_GRAPHVIZ_TOOLS = 'dot twopi neato circo fdp'.split()
20
21 def seek(cmd):
22 """Returns the first valid path for cmd in $PATH or None."""
23 for directory in os.environ['PATH'].split(os.pathsep):
24 filepath = os.path.join(directory,cmd)
25 if os.path.exists(filepath):
26 return filepath
27 return None
28
29 class Parser:
30 """ MoinMoin graphViz parser."""
31 extensions = []
32 Dependencies = []
33
34 def __init__(self, raw, request, **kw):
35 """ Validate and store arguments provided by Moin.
36
37 self.raw = raw text provided
38 self.formatter = formatter provided by the user
39 """
40 # get the formatter from the 'commandline'
41 self.formatter = kw.get('format_args','dot').strip()
42 # validate if it's save...
43 if self.formatter.lower() not in VALID_GRAPHVIZ_TOOLS:
44 self.error_msg = "%r is not a valid formatter" % \
45 self.formatter
46 # if we're on windows: add .exe to make things work
47 if os.name == 'nt':
48 self.formatter += ".exe"
49 print `self.formatter`
50 # set self.formatter to the path leading to the formatter
51 self.formatter = seek(self.formatter)
52 # provide an error if no file in $PATH could be found
53 if self.formatter is None:
54 self.error_msg = "Cannot find executable for %r" % \
55 self.formatter
56 # store the raw and request for later processing
57 self.raw = raw
58 self.request = request
59 # find the attachments directory for this page
60 self.store_attachments_in = \
61 request.formatter.page.getPagePath('attachments')
62 # investigate whether a map file is required
63 self.need_map = raw.find('URL') > -1
64 # create a unique identifier within this page
65 self.fingerprint = sha.new(raw).hexdigest()
66 # calculate the png name
67 self.png_filename = os.path.join(self.store_attachments_in,
68 'diagram-'+self.fingerprint+'.png')
69 # calculate the map name
70 self.map_filename = os.path.join(self.store_attachments_in,
71 'diagram-'+self.fingerprint+'.map')
72
73
74 def generate_files(self):
75 """Produce the png file (and optionally the map file)."""
76 # check if the cached result is enough
77 if os.path.exists(self.png_filename) and \
78 (os.path.exists(self.map_filename) or not self.need_map):
79 return
80 # determine the commandline for generating the image
81 cmdline = '%s -Tpng -Gbgcolor=transparent -o %s' % \
82 (self.formatter,self.png_filename)
83 p = os.popen(cmdline, 'w')
84 p.write(self.raw)
85 p.close()
86 if self.need_map:
87 # if the map file is required create that one as well
88 cdmline = '%s -Tcmap -o %s' % \
89 (self.formatter, self.map_filename)
90 p = os.popen('dot -Tcmap -o ' + self.map_filename, 'w')
91 p.write(self.raw)
92 p.close()
93
94
95 def format(self, formatter):
96 if hasattr(self,'error_msg'):
97 # handle stored errors by printing them
98 # and returning immidiatly
99 self.request.write(formatter.text(
100 wikiutil.escape(self.error_msg)))
101 return
102 self.generate_files()
103 img_url = AttachFile.getAttachUrl(
104 formatter.page.page_name,
105 os.path.split(self.png_filename)[1],
106 self.request)
107 if self.need_map:
108 # write html to show the image and linked to a map
109 self.request.write(
110 formatter.image(src = img_url,
111 usemap = '#' + self.fingerprint,
112 border = 0,
113 ismap = True))
114 # read map from disk
115 p = open(self.map_filename, 'r')
116 map_contents = p.read()
117 p.close()
118 # write the map html to the stream
119 map_html = '<MAP name="'+ self.fingerprint + '">\n'+ \
120 map_contents + '</MAP>'
121 self.request.write(formatter.rawHTML(map_html))
122 else:
123 # write a line to include the graphic
124 self.request.write(formatter.image(src = img_url))
125
126
127 ##class Snippets:
128 ## STD_GRAPH_HEADER = '''overlap=false
129 ## node [fontname=Verdana fontsize=10 style=filled fillcolor=azure color=steelblue fontcolor=steelblue]
130 ## edge [fontname=Verdana fontsize=8 color=steelblue fontcolor=steelblue]'''
131 ##
132 ## ATTEMPT_TO_JOIN_EDGES = 'concentrate=true'
133 ## LEFT_TO_RIGHT = 'rankdir=LR'
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.