Takeshi Komiya avatar Takeshi Komiya committed 3485321

* Add sphinxcontrib-actdiag package

Comments (0)

Files changed (11)

 
 blockdiag:
    Takeshi KOMIYA <i.tkomiya@gmail.com>
+
+actdiag:
+   Takeshi KOMIYA <i.tkomiya@gmail.com>
 - spelling: Spelling checker using PyEnchant_
 - sadisplay: display SqlAlchemy model sadisplay_
 - blockdiag: embed block diagrams by using blockdiag_
+- actdiag: embed block diagrams by using actdiag_
 
 .. _aafigure: http://docutils.sourceforge.net/sandbox/aafigure/
 
 
 .. _blockdiag: http://blockdiag.com/
 
+.. _actdiag: http://blockdiag.com/
+
 
 For contributors
 ================
+Takeshi KOMIYA <i.tkomiya@gmail.com>
+If not otherwise noted, the extensions in this package are licensed
+under the following license.
+
+Copyright (c) 2009 by the contributors (see AUTHORS file).
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

actdiag/MANIFEST.in

+include AUTHORS
+include LICENSE
+include README
+include CHANGES.*
+actdiag extension README
+========================
+This is a sphinx extension which render block diagrams by using
+`actdiag <http://bitbucket.org/tk0miya/actdiag/>`_ .
+
+rendered:
+
+.. actdiag::
+
+   diagram {
+     A -> B -> C -> D;
+
+     lane {
+       A; B;
+     }
+     lane {
+       C; D;
+     }
+   }
+
+source:
+
+.. code-block:: text
+
+   .. actdiag::
+
+      diagram {
+        A -> B -> C -> D;
+
+        lane {
+          A; B;
+        }
+        lane {
+          C; D;
+        }
+      }
+
+Setting
+=======
+.. You can see available package at `PyPI <http://pypi.python.org/pypi/sphinxcontrib-actdiag>`_.
+
+You can get archive file at http://bitbucket.org/birkenfeld/sphinx-contrib/
+
+Required components
+-------------------
+* `actdiag <http://bitbucket.org/tk0miya/actdiag>`_ .
+
+Install
+-------
+
+.. code-block:: bash
+
+   > easy_install sphinxcontrib-actdiag
+
+
+Configure Sphinx
+----------------
+To enable this extension, add ``sphinxcontrib.actdiag`` module to extensions 
+option at :file:`conf.py`. 
+
+.. code-block:: python
+
+   import os, sys
+
+   # Path to the folder where actdiag.py is
+   # NOTE: not needed if the package is installed in traditional way
+   # using setup.py or easy_install
+   sys.path.append(os.path.abspath('/path/to/sphinxcontrib.actdiag'))
+
+   # Enabled extensions
+   extensions = ['sphinxcontrib.actdiag']
+
+
+Directive
+=========
+
+.. describe:: .. actdiag:: [filename]
+
+   This directive insert a block diagram into the generated document.
+   If filename is specified, sphinx reads external file as source script of blockfile.
+   In another case, actdiag directive takes code block as source script.
+
+   Examples::
+
+      .. actdiag:: foobar.diag
+
+      .. actdiag::
+
+         diagram {
+            // some diagrams are here.
+         }
+
+
+Configuration File Options
+==========================
+
+.. confval:: actdiag_fontpath
+
+   This is a path for renderring fonts. You can use truetype font (.ttf) file path.
+
+.. confval:: actdiag_antialias
+
+   If :confval:`actdiag_antialias: is True, actdiag generates images
+   with anti-alias filter.
+
+
+Repository
+==========
+This code is hosted by Bitbucket.
+
+  http://bitbucket.org/birkenfeld/sphinx-contrib/

actdiag/setup.cfg

+[egg_info]
+;tag_build = dev
+;tag_date = true
+
+[aliases]
+release = egg_info -RDb ''
+# -*- coding: utf-8 -*-
+
+from setuptools import setup, find_packages
+
+long_desc = '''
+This package contains the actdiag Sphinx extension.
+
+.. add description here ..
+'''
+
+requires = ['actdiag>=0.1.5', 'Sphinx>=0.6']
+
+setup(
+    name='sphinxcontrib-actdiag',
+    version='0.1.0',
+    url='http://bitbucket.org/birkenfeld/sphinx-contrib',
+    download_url='http://pypi.python.org/pypi/sphinxcontrib-actdiag',
+    license='BSD',
+    author='Takeshi Komiya',
+    author_email='i.tkomiya@gmail.com',
+    description='Sphinx "actdiag" extension',
+    long_description=long_desc,
+    zip_safe=False,
+    classifiers=[
+        'Development Status :: 4 - Beta',
+        'Environment :: Console',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Topic :: Documentation',
+        'Topic :: Utilities',
+    ],
+    platforms='any',
+    packages=find_packages(),
+    include_package_data=True,
+    install_requires=requires,
+    namespace_packages=['sphinxcontrib'],
+)

actdiag/sphinxcontrib/__init__.py

+# -*- coding: utf-8 -*-
+"""
+    sphinxcontrib
+    ~~~~~~~~~~~~~
+
+    This package is a namespace package that contains all extensions
+    distributed in the ``sphinx-contrib`` distribution.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+__import__('pkg_resources').declare_namespace(__name__)
+

actdiag/sphinxcontrib/actdiag.py

+# -*- coding: utf-8 -*-
+"""
+    actdiag.sphinx_ext
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Allow actdiag-formatted diagrams to be included in Sphinx-generated
+    documents inline.
+
+    :copyright: Copyright 2010 by Takeshi Komiya.
+    :license: BSDL.
+"""
+
+import posixpath
+import os
+import codecs
+try:
+    from hashlib import sha1 as sha
+except ImportError:
+    from sha import sha
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+
+from sphinx.errors import SphinxError
+from sphinx.util.osutil import ensuredir, ENOENT, EPIPE
+from sphinx.util.compat import Directive
+
+from actdiag_sphinxhelper import diagparser, builder, DiagramDraw
+
+
+class ActdiagError(SphinxError):
+    category = 'Actdiag error'
+
+
+class actdiag(nodes.General, nodes.Element):
+    pass
+
+
+class Actdiag(Directive):
+    """
+    Directive to insert arbitrary dot markup.
+    """
+    has_content = True
+    required_arguments = 0
+    optional_arguments = 1
+    final_argument_whitespace = False
+    option_spec = {
+        'alt': directives.unchanged,
+        'desctable': directives.flag,
+        'maxwidth': directives.nonnegative_int,
+    }
+
+    def run(self):
+        if self.arguments:
+            document = self.state.document
+            if self.content:
+                return [document.reporter.warning(
+                    'actdiag directive cannot have both content and '
+                    'a filename argument', line=self.lineno)]
+            env = self.state.document.settings.env
+            rel_filename, filename = relfn2path(env, self.arguments[0])
+            env.note_dependency(rel_filename)
+            try:
+                fp = codecs.open(filename, 'r', 'utf-8')
+                try:
+                    dotcode = fp.read()
+                finally:
+                    fp.close()
+            except (IOError, OSError):
+                return [document.reporter.warning(
+                    'External actdiag file %r not found or reading '
+                    'it failed' % filename, line=self.lineno)]
+        else:
+            dotcode = '\n'.join(self.content)
+            if not dotcode.strip():
+                return [self.state_machine.reporter.warning(
+                    'Ignoring "actdiag" directive without content.',
+                    line=self.lineno)]
+
+        node = actdiag()
+        node['code'] = dotcode
+        node['options'] = {}
+        if 'alt' in self.options:
+            node['alt'] = self.options['alt']
+        if 'maxwidth' in self.options:
+            node['options']['maxwidth'] = self.options['maxwidth']
+        if 'desctable' in self.options:
+            node['options']['desctable'] = self.options['desctable']
+        return [node]
+
+
+# compatibility to sphinx 1.0 (ported from sphinx trunk)
+def relfn2path(env, filename, docname=None):
+    if filename.startswith('/') or filename.startswith(os.sep):
+        rel_fn = filename[1:]
+    else:
+        docdir = os.path.dirname(env.doc2path(docname or env.docname,
+                                              base=None))
+        rel_fn = os.path.join(docdir, filename)
+    try:
+        return rel_fn, os.path.join(env.srcdir, rel_fn)
+    except UnicodeDecodeError:
+        # the source directory is a bytestring with non-ASCII characters;
+        # let's try to encode the rel_fn in the file system encoding
+        enc_rel_fn = rel_fn.encode(sys.getfilesystemencoding())
+        return rel_fn, os.path.join(env.srcdir, enc_rel_fn)
+
+
+def get_image_filename(self, code, format, options, prefix='actdiag'):
+    """
+    Get path of output file.
+    """
+    if format not in ('PNG', 'PDF'):
+        raise ActdiagError('actdiag error:\nunknown format: %s\n' % format)
+
+    if format == 'PDF':
+        try:
+            import reportlab
+        except ImportError:
+            msg = 'actdiag error:\n' + \
+                  'colud not output PDF format; Install reportlab\n'
+            raise ActdiagError(msg)
+
+    hashkey = code.encode('utf-8') + str(options)
+    fname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), format.lower())
+    if hasattr(self.builder, 'imgpath'):
+        # HTML
+        relfn = posixpath.join(self.builder.imgpath, fname)
+        outfn = os.path.join(self.builder.outdir, '_images', fname)
+    else:
+        # LaTeX
+        relfn = fname
+        outfn = os.path.join(self.builder.outdir, fname)
+
+    if os.path.isfile(outfn):
+        return relfn, outfn
+
+    ensuredir(os.path.dirname(outfn))
+
+    return relfn, outfn
+
+
+def create_actdiag(self, code, format, filename, options, prefix='actdiag'):
+    """
+    Render actdiag code into a PNG output file.
+    """
+    fontpath = self.builder.config.actdiag_fontpath
+    if fontpath and not hasattr(self.builder, '_actdiag_fontpath_warned'):
+        if not os.path.isfile(fontpath):
+            self.builder.warn('actdiag cannot load "%s" as truetype font, '
+                              'check the actdiag_path setting' % fontpath)
+            self.builder._actdiag_fontpath_warned = True
+
+    draw = None
+    try:
+        tree = diagparser.parse(diagparser.tokenize(code))
+        screen = builder.ScreenNodeBuilder.build(tree)
+
+        antialias = self.builder.config.actdiag_antialias
+        draw = DiagramDraw.DiagramDraw(format, screen, filename, font=fontpath,
+                                       antialias=antialias)
+    except Exception, e:
+        raise ActdiagError('actdiag error:\n%s\n' % e)
+
+    return draw
+
+
+def render_dot_html(self, node, code, options, prefix='actdiag',
+                    imgcls=None, alt=None):
+    has_thumbnail = False
+    try:
+        format = 'PNG'
+        relfn, outfn = get_image_filename(self, code, format, options, prefix)
+
+        image = create_actdiag(self, code, format, outfn, options, prefix)
+        if not os.path.isfile(outfn):
+            image.draw()
+            image.save()
+
+        # generate description table
+        descriptions = []
+        if 'desctable' in options:
+            for n in image.screen.nodes:
+                if n.description:
+                    descriptions.append((n.id, n.numbered, n.description))
+
+        # generate thumbnails
+        image_size = image.drawer.image.size
+        if 'maxwidth' in options and options['maxwidth'] < image_size[0]:
+            has_thumbnail = True
+            thumb_prefix = prefix + '_thumb'
+            trelfn, toutfn = get_image_filename(self, code, format,
+                                                options, thumb_prefix)
+
+            thumb_size = (options['maxwidth'], image_size[1])
+            if not os.path.isfile(toutfn):
+                image.draw()
+                image.save(toutfn, thumb_size)
+            thumb_size = image.drawer.image.size
+
+    except ActdiagError, exc:
+        self.builder.warn('dot code %r: ' % code + str(exc))
+        raise nodes.SkipNode
+
+    self.body.append(self.starttag(node, 'p', CLASS='actdiag'))
+    if relfn is None:
+        self.body.append(self.encode(code))
+    else:
+        if alt is None:
+            alt = node.get('alt', self.encode(code).strip())
+
+        imgtag_format = '<img src="%s" alt="%s" width="%s" height="%s" />\n'
+        if has_thumbnail:
+            self.body.append('<a href="%s">' % relfn)
+            self.body.append(imgtag_format %
+                             (trelfn, alt, thumb_size[0], thumb_size[1]))
+            self.body.append('</a>')
+        else:
+            self.body.append(imgtag_format %
+                             (relfn, alt, image_size[0], image_size[1]))
+
+    if descriptions:
+        numbered = [x for x in descriptions if x[1]]
+
+        self.body.append('<table border="1" class="docutils">')
+        self.body.append('<thead valign="bottom">')
+        if numbered:
+            self.body.append('<tr><th class="head">No</th><th class="head">Name</th><th class="head">Description</th></tr>')
+        else:
+            self.body.append('<tr><th class="head">Name</th><th class="head">Description</th></tr>')
+        self.body.append('</thead>')
+        self.body.append('<tbody valign="top">')
+
+        if numbered:
+            def cmp_number(a, b):
+                if a[1]:
+                    n1 = int(a[1])
+                else:
+                    n1 = 0
+
+                if b[1]:
+                    n2 = int(b[1])
+                else:
+                    n2 = 0
+
+                return cmp(n1, n2)
+
+            descriptions.sort(cmp_number)
+
+        for desc in descriptions:
+            id, number, text = desc
+            self.body.append('<tr>')
+            if numbered:
+                if number is not None:
+                    self.body.append('<td>%s</td>' % number)
+                else:
+                    self.body.append('<td></td>')
+            self.body.append('<td>%s</td>' % id)
+            self.body.append('<td>%s</td>' % text)
+            self.body.append('</tr>')
+
+        self.body.append('</tbody>')
+        self.body.append('</table>')
+
+    self.body.append('</p>\n')
+    raise nodes.SkipNode
+
+
+def html_visit_actdiag(self, node):
+    render_dot_html(self, node, node['code'], node['options'])
+
+
+def render_dot_latex(self, node, code, options, prefix='actdiag'):
+    try:
+        format = self.builder.config.actdiag_tex_image_format
+        fname, outfn = get_image_filename(self, code, format, options, prefix)
+
+        image = create_actdiag(self, code, format, outfn, options, prefix)
+        if not os.path.isfile(outfn):
+            image.draw()
+            image.save()
+
+    except ActdiagError, exc:
+        self.builder.warn('dot code %r: ' % code + str(exc))
+        raise nodes.SkipNode
+
+    if fname is not None:
+        self.body.append('\\par\\includegraphics{%s}\\par' % fname)
+    raise nodes.SkipNode
+
+
+def latex_visit_actdiag(self, node):
+    render_dot_latex(self, node, node['code'], node['options'])
+
+
+def setup(app):
+    app.add_node(actdiag,
+                 html=(html_visit_actdiag, None),
+                 latex=(latex_visit_actdiag, None))
+    app.add_directive('actdiag', Actdiag)
+    app.add_config_value('actdiag_fontpath', None, 'html')
+    app.add_config_value('actdiag_antialias', False, 'html')
+    app.add_config_value('actdiag_tex_image_format', 'PNG', 'html')
+## configuration for tox <http://codespeak.net/tox/>
+
+## tox automates running certain tasks within virtualenvs.  The following
+## tox configuration outlines a basic setup for running unit tests and
+## building sphinx docs in separate virtual environments.  Give it a try!
+
+[tox]
+envlist=python,doc
+
+# test running
+[testenv:python]
+deps=
+    ## if you use nose for test running
+    # nose
+    ## if you use py.test for test running
+    # pytest
+commands=
+    ## run tests with py.test
+    # py.test []
+    ## run tests with nose
+    # nose
+
+[testenv:doc]
+deps=
+    sphinx
+    # add all Sphinx extensions and other dependencies required to build your docs
+commands=
+    ## test links
+    # sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees doc {envtmpdir}/linkcheck
+    ## test html output
+    # sphinx-build -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.