# HG changeset patch # User Paul Boddie # Date 1326564046 -3600 # Node ID 0091f58eb0aef401b463826374abffcf3a3f6086 # Parent a70b2bf1a1a0dedabc617dd14bd470416eb607e8 Tidied class and instance attribute usage. Added a dependency on "pages". Moved the parser usage instructions to a separate file. Removed "cmapx" as a permissible standalone output format. diff -r a70b2bf1a1a0 -r 0091f58eb0ae README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.txt Sat Jan 14 19:00:46 2012 +0100 @@ -0,0 +1,65 @@ +Basic Usage +----------- + +Embed a visualization of a graph in a wiki page: + +{{{#!graphviz +digraph G { + A -> B; +}; +}}} + +Advanced Usage +-------------- + +This parser will check the first lines of the Graphviz data for C++ style +comments instructing it to use a different filter (dot, neato, twopi, circo, +or fdp - see http://graphviz.org/ for more info), use a different format for +the output (see the FORMATS list in the Parser class), or to generate and pass +a client-side image map. + +Options: + +filter - the filter to use (see Parser.FILTERS) +format - the output format (see Parser.FORMATS) +cmapx - the map name to use for the client-side image map; this must match + the graph name in the graph definition and shouldn't conflict with + any other graphs that are used on the same page; for SVG images, the + cmapx option is superfluous since SVG supports linking natively and + Graphviz converts "href" attributes appropriately + +Embed a visualization of a graph in a wiki page, using the dot filter and +providing a client-side image map (the filter=dot and format=png options are +redundant since those are the defaults for this parser): + +{{{#!graphviz +//filter=dot +//format=png +//cmapx=DocumentationMap +digraph DocumentationMap { + FrontPage [href="FrontPage", root=true]; + HelpOnEditing [href="HelpOnEditing"]; + SyntaxReference [href="SyntaxReference"]; + WikiSandBox [href="WikiSandBox", color="grey"]; + MoinMoin [href="http://moinmo.in"]; + FrontPage -> WikiSandBox; + FrontPage -> MoinMoin; + WikiSandBox -> HelpOnEditing; + WikiSandBox -> SyntaxReference; + SyntaxReference -> FrontPage; +}; +}}} + +Known Bugs +---------- + + - Hasn't been thoroughly checked for potential methods of injecting + arbitrary HTML into the output. + - Only compatible with HTML rendering + - May not use all of the MoinMoin interfaces properly - this is a + quick hack based on looking at an example and digging through the + MoinMoin source. The MoinMoin development docs haven't been + consulted (yet). + - Comments must start at the beginning of the graphviz block, and at the + beginning of their respective lines. They must also not contain + any extra whitespace surrounding the = sign. diff -r a70b2bf1a1a0 -r 0091f58eb0ae graphviz.py --- a/graphviz.py Sat Jan 14 16:35:38 2012 +0100 +++ b/graphviz.py Sat Jan 14 19:00:46 2012 +0100 @@ -8,74 +8,12 @@ @license: GNU GPL, see COPYING for details. """ -""" - BASIC USAGE: - - embed a visualization of a graph in a wiki page: - -{{{#!graphviz -digraph G { - A -> B; -}; -}}} - - ADVANCED USAGE: - - This parser will check the first lines of the Graphviz data for C++ style - comments instructing it to use a different filter (dot, neato, twopi, - circo, or fdp - see http://graphviz.org/ for more info), use a different - format for the output (see the FORMATS list in the Parser class below), - or to generate and pass a client-side image map. - - Options: - filter - the filter to use (see Parser.FILTERS) - format - the output format (see Parser.FORMATS) - cmapx - the map name to use for the client-side image map. Must match - the graph name in the graph definition and shouldn't conflict - with any other graphs that are used on the same page. - - embed a visualization of a graph in a wiki page, using the dot filter and - providing a client-side image map (the filter=dot and format=png options are - redundant since those are the defaults for this parser): - -{{{#!graphviz -//filter=dot -//format=png -//cmapx=DocumentationMap -digraph DocumentationMap { - FrontPage [href="FrontPage", root=true]; - HelpOnEditing [href="HelpOnEditing"]; - SyntaxReference [href="SyntaxReference"]; - WikiSandBox [href="WikiSandBox", color="grey"]; - MoinMoin [href="http://moinmo.in"]; - FrontPage -> WikiSandBox; - FrontPage -> MoinMoin; - WikiSandBox -> HelpOnEditing; - WikiSandBox -> SyntaxReference; - SyntaxReference -> FrontPage; -}; -}}} - - - KNOWN BUGS: - - Hasn't been thoroughly checked for potential methods of injecting - arbitrary HTML into the output. - - Only compatible with HTML rendering - - May not use all of the MoinMoin interfaces properly - this is a - quick hack based on looking at an example and digging through the - MoinMoin source. The MoinMoin development docs haven't been - consulted (yet). - - Comments must start at the beginning of the graphviz block, and at the - beginning of their respective lines. They must also not contain - any extra whitespace surrounding the = sign. - -""" - # Change this to the directory that the Graphviz binaries (dot, neato, etc.) # are installed in. BINARY_PATH = '/usr/bin' +from os.path import join import os import subprocess import sha @@ -91,19 +29,20 @@ class GraphVizError(RuntimeError): pass -Dependencies = [] +Dependencies = ["pages"] class Parser: - """Uses the Graphviz programs to create a visualization of a graph.""" + + "Uses the Graphviz programs to create a visualization of a graph." + + extensions = [] + Dependencies = Dependencies FILTERS = ['dot', 'neato', 'twopi', 'circo', 'fdp'] IMAGE_FORMATS = ['png', 'gif'] - OBJECT_FORMATS = ['svg', 'svgz'] - OUTPUT_FORMATS = IMAGE_FORMATS + OBJECT_FORMATS - FORMATS = OUTPUT_FORMATS + \ - ['ps', 'fig', 'mif', 'hpgl', 'pcl', 'dia', 'imap', 'cmapx'] - extensions = [] - Dependencies = Dependencies + SVG_FORMATS = ['svg', 'svgz'] + OUTPUT_FORMATS = IMAGE_FORMATS + SVG_FORMATS + \ + ['ps', 'fig', 'mif', 'hpgl', 'pcl', 'dia', 'imap'] attach_regexp = re.compile( r"graphviz_" @@ -136,7 +75,7 @@ request.flush() # to identify error text - self.filter = Parser.FILTERS[0] + filter = self.FILTERS[0] format = 'png' cmapx = None width = None @@ -153,47 +92,55 @@ if directive == 'filter': filter = value.lower() - if filter in Parser.FILTERS: - self.filter = filter - else: + if filter not in self.FILTERS: logging.warn('unknown filter %s' % filter) elif directive == 'format': value = value.lower() - if value in Parser.FORMATS: + if value in self.OUTPUT_FORMATS: format = value elif directive == 'cmapx': cmapx = wikiutil.escape(value) - if not format in Parser.OUTPUT_FORMATS: + if not format in self.OUTPUT_FORMATS: raise NotImplementedError, "only formats %s are currently supported" % \ - Parser.OUTPUT_FORMATS + self.OUTPUT_FORMATS - if cmapx: - if not format in Parser.IMAGE_FORMATS: - logging.warn('format %s is incompatible with cmapx option' % format) - cmapx = None + if cmapx and not format in self.IMAGE_FORMATS: + logging.warn('format %s is incompatible with cmapx option' % format) + cmapx = None digest = sha.new(self.raw).hexdigest() - self.pagename = formatter.page.page_name - self.attach_dir = AttachFile.getAttachDir(request, self.pagename, create=1) + # Make sure that an attachments directory exists and that old graphs are + # deleted. + + self.attach_dir = AttachFile.getAttachDir(request, page.page_name, create=1) self.delete_old_graphs(formatter) + # Find the details of the graph, rendering a new graph if necessary. + attrs = self.find_graph(digest, format) if not attrs: - attrs = self.graphviz(self.raw, digest, format) + attrs = self.graphviz(filter, self.raw, digest, format) chart = self.get_chartname(digest, format, attrs) - url = AttachFile.getAttachUrl(self.pagename, chart, request) + url = AttachFile.getAttachUrl(page.page_name, chart, request) - if format in Parser.IMAGE_FORMATS: + # Images are displayed using the HTML "img" element (or equivalent) + # and may provide an imagemap. + + if format in self.IMAGE_FORMATS: if cmapx: - request.write('\n' + self.graphviz(self.raw, digest, "cmapx") + '\n') + request.write('\n' + self.graphviz(filter, self.raw, digest, "cmapx") + '\n') request.write(formatter.image(src="%s" % url, usemap="#%s" % cmapx, **self.get_format_attrs(attrs))) else: request.write(formatter.image(src="%s" % url, alt="graphviz image", **self.get_format_attrs(attrs))) + + # Other objects are embedded using the HTML "object" element (or + # equivalent). + else: request.write(formatter.transclusion(1, data=url, **self.get_format_attrs(attrs))) request.write(formatter.text(_("graphviz image"))) @@ -203,7 +150,7 @@ "Find an existing graph using 'digest' and 'format'." - attach_files = AttachFile._get_files(self.request, self.pagename) + attach_files = AttachFile._get_files(self.request, self.request.page.page_name) for chart in attach_files: match = self.attach_regexp.match(chart) @@ -237,23 +184,26 @@ except KeyError, ex: return - attach_files = AttachFile._get_files(self.request, self.pagename) + attach_files = AttachFile._get_files(self.request, self.request.page.page_name) for chart in attach_files: match = self.attach_regexp.match(chart) - if match and match.group("format") in Parser.FORMATS: - fullpath = os.path.join(self.attach_dir, chart).encode(config.charset) + if match and match.group("format") in self.OUTPUT_FORMATS: + fullpath = join(self.attach_dir, chart).encode(config.charset) st = os.stat(fullpath) chart_date = self.request.user.getFormattedDateTime(st.st_mtime) if chart_date < page_date: os.remove(fullpath) - def graphviz(self, graph_def, digest, format): + def graphviz(self, filter, graph_def, digest, format): - "Using the 'graph_def' and 'digest', generate output in the given 'format'." + """ + Using the 'filter' with the given 'graph_def' (and 'digest'), generate + output in the given 'format'. + """ - p = subprocess.Popen(['%s/%s' % (BINARY_PATH, self.filter), '-T%s' % format], shell=False, \ + p = subprocess.Popen([join(BINARY_PATH, filter), '-T%s' % format], shell=False, \ stdin=subprocess.PIPE, \ stdout=subprocess.PIPE, \ stderr=subprocess.PIPE) @@ -277,7 +227,7 @@ if format != "cmapx": chart = self.get_chartname(digest, format, attrs) - filename = os.path.join(self.attach_dir, chart).encode(config.charset) + filename = join(self.attach_dir, chart).encode(config.charset) f = open(filename, "wb") try: