seqdiag-0.9.0/0000755000175000017500000000000012224000732014341 5ustar katsuwokatsuwo00000000000000seqdiag-0.9.0/seqdiag.10000644000175000017500000000376511644721254016071 0ustar katsuwokatsuwo00000000000000.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH SEQDIAG 1 "May 21, 2011" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME seqdiag \- generate sequence-diagram image file from spec-text file. .SH SYNOPSIS .B seqdiag .RI [ options ] " file" .br .SH DESCRIPTION This manual page documents briefly the .B seqdiag commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBseqdiag\fP is generate sequence-diagram image file from spec-text file. .SH OPTIONS These programs follow the usual GNU command line syntax, with long options starting with two dashes (`-'). A summary of options is included below. For a complete description, see the Info files. .TP .B \-\-version show program's version number and exit .TP .B \-h, \-\-help show this help message and exit .TP .B \-a, \-\-antialias Pass diagram image to anti-alias filter .TP .B \-c FILE, \-\-config=FILE read configurations from FILE .TP .B \-o FILE write diagram to FILE .TP .B \-f FONT, \-\-font=FONT use FONT to draw diagram .TP .B \-T TYPE Output diagram as TYPE format .SH SEE ALSO .BR .br The programs are documented fully by .br .IR http://tk0miya.bitbucket.org/seqdiag/build/html/index.html .SH AUTHOR seqdiag was written by Takeshi Komiya .PP This manual page was written by Kouhei Maeda , for the Debian project (and may be used by others). seqdiag-0.9.0/buildout.cfg0000644000175000017500000000120112223736353016661 0ustar katsuwokatsuwo00000000000000[buildout] parts = seqdiag test coverage tox pyflakes pylint develop = . [seqdiag] recipe = zc.recipe.egg eggs = seqdiag interpreter = py [test] recipe = pbp.recipe.noserunner eggs = seqdiag[rst] seqdiag[test] coverage unittest-xml-reporting [coverage] recipe = zc.recipe.egg eggs = coverage [tox] recipe = zc.recipe.egg eggs = tox detox [pyflakes] recipe = zc.recipe.egg eggs = pyflakes scripts = pyflakes entry-points = pyflakes=pyflakes.scripts.pyflakes:main [pylint] recipe = zc.recipe.egg eggs = pylint seqdiag[test] seqdiag[rst] scripts = pylint seqdiag-0.9.0/PKG-INFO0000644000175000017500000002136412224000732015444 0ustar katsuwokatsuwo00000000000000Metadata-Version: 1.1 Name: seqdiag Version: 0.9.0 Summary: seqdiag generate sequence-diagram image file from spec-text file. Home-page: http://blockdiag.com/ Author: Takeshi Komiya Author-email: i.tkomiya at gmail.com License: Apache License 2.0 Download-URL: http://pypi.python.org/pypi/seqdiag Description: `seqdiag` generate sequence-diagram image file from spec-text file. Features ======== * Generate sequence-diagram from dot like text (basic feature). * Multilingualization for node-label (utf-8 only). You can get some examples and generated images on `blockdiag.com `_ . Setup ===== by easy_install ---------------- Make environment:: $ easy_install seqdiag by buildout ------------ Make environment:: $ hg clone http://bitbucket.org/tk0miya/seqdiag $ cd seqdiag $ python bootstrap.py $ bin/buildout Copy and modify ini file. example:: $ cp /blockdiag/examples/simple.diag . $ vi simple.diag Please refer to `spec-text setting sample`_ section for the format of the `simpla.diag` configuration file. spec-text setting sample ======================== Few examples are available. You can get more examples at `blockdiag.com `_ . simple.diag ------------ simple.diag is simply define nodes and transitions by dot-like text format:: diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } Usage ===== Execute seqdiag command:: $ seqdiag simple.diag $ ls simple.png simple.png Requirements ============ * Python 2.6, 2.7, 3.2, 3.3 * Pillow 2.2.1 * funcparserlib 0.3.6 * setuptools License ======= Apache License 2.0 History ======= 0.9.0 (2013-10-05) ------------------ * Support python 3.2 and 3.3 (thanks to @masayuko) * Drop supports for python 2.4 and 2.5 * Replace dependency: PIL -> Pillow 0.8.2 (2013-02-09) ------------------ * Fix bugs 0.8.1 (2012-11-12) ------------------ * Add altblock feature (experimental) * Fix bugs 0.8.0 (2012-10-22) ------------------ * Optimize algorithm for rendering shadow * Add options to docutils directive * Fix bugs 0.7.5 (2012-09-29) ------------------ * Fix bugs 0.7.4 (2012-09-20) ------------------ * Support blockdiag-1.1.7 interface * Fix bugs 0.7.3 (2012-03-16) ------------------ * Allow to insert separators in subedge-group * Fix bugs 0.7.2 (2011-12-12) ------------------ * Fix bugs 0.7.1 (2011-11-30) ------------------ * Fix bugs 0.7.0 (2011-11-19) ------------------ * Add fontfamily attribute for switching fontface * Fix bugs 0.6.3 (2011-11-06) ------------------ * Add docutils extention * Fix bugs 0.6.2 (2011-11-01) ------------------ * Add class feature (experimental) 0.6.1 (2011-11-01) ------------------ * Follow blockdiag-0.9.7 interface 0.6.0 (2011-10-28) ------------------ * Add edge attributes: note, rightnote, leftnote, notecolor * Add diagram atteribute: default_note_color 0.5.2 (2011-10-27) ------------------ * Implement auto edge height adjusting * Fix bugs 0.5.1 (2011-10-24) ------------------ * Fix bugs 0.5.0 (2011-10-21) ------------------ * Add diagram attributes: activation, autonumber * Add edge attribute: failed * Add separator syntax 0.4.3 (2011-10-19) ------------------ * Follow blockdiag-0.9.5 interface 0.4.2 (2011-10-11) ------------------ * Fix bugs 0.4.1 (2011-09-30) ------------------ * Add diagram attribute: default_text_color * Add node attribte: textcolor * Fix bugs 0.4.0 (2011-09-26) ------------------ * Add diagram attributes: default_node_color, default_group_color and default_line_color 0.3.8 (2011-08-02) ------------------ * Allow dot characters in node_id * Fix bugs 0.3.7 (2011-07-05) ------------------ * Fix bugs 0.3.6 (2011-07-03) ------------------ * Support input from stdin 0.3.5 (2011-06-02) ------------------ * Fix bugs 0.3.4 (2011-05-18) ------------------ * Fix bugs 0.3.3 (2011-05-16) ------------------ * Add --version option * Add sphinxhelper module 0.3.2 (2011-05-14) ------------------ * Render group label * Support blockdiag 0.8.1 core interface 0.3.1 (2011-04-22) ------------------ * Render group label * Fix sphinxcontrib_seqdiag does not work with seqdiag 0.3.0 0.3.0 (2011-04-22) ------------------ * Add group syntax 0.2.7 (2011-04-15) ------------------ * Adjust start coordinates of edges 0.2.6 (2011-04-14) ------------------ * Fix bugs * Allow unquoted utf8 characters 0.2.5 (2011-03-26) ------------------ * Fix seqdiag could not run under blockdiag 0.7.6 0.2.4 (2011-03-20) ------------------ * Fix bugs 0.2.3 (2011-03-09) ------------------ * Fix bugs 0.2.2 (2011-03-07) ------------------ * Fix could not run under python 2.4 * Support edge colors 0.2.1 (2011-02-28) ------------------ * Add default_shape attribute to diagram 0.2.0 (2011-02-27) ------------------ * Add metrix parameters for edge label: edge_height, edge_length * Fix bugs 0.1.7 (2011-01-21) ------------------ * Fix TeX exporting in Sphinx extension 0.1.6 (2011-01-15) ------------------ * Support blockdiag-0.6.3 * Fix bugs 0.1.5 (2011-01-15) ------------------ * Draw activity on lifelines * Support both direction edge with '=>' operator 0.1.4 (2011-01-13) ------------------ * Change synxtax around edges 0.1.3 (2011-01-12) ------------------ * Support diagonal edge * Fix bugs 0.1.2 (2011-01-11) ------------------ * Support nested edges * Add edge attributes; return, dir * Add sphinx extention module(sphinxcontrib_seqdiag) * Fix bugs 0.1.1 (2011-01-11) ------------------ * Fix bugs about layouting 0.1.0 (2011-01-08) ------------------ * first release Keywords: diagram,generator Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Documentation Classifier: Topic :: Text Processing :: Markup seqdiag-0.9.0/setup.py0000644000175000017500000000344412223771027016073 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- from setuptools import setup, find_packages import os, sys sys.path.insert(0, 'src') import seqdiag long_description = open(os.path.join("src","README.txt")).read() classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Topic :: Software Development", "Topic :: Software Development :: Documentation", "Topic :: Text Processing :: Markup", ] test_requires = [ 'Nose', 'pep8>=1.3',] # only for Python2.6 if sys.version_info > (2, 6) and sys.version_info < (2, 7): test_requires.append('unittest2') setup( name='seqdiag', version=seqdiag.__version__, description='seqdiag generate sequence-diagram image file from spec-text file.', long_description=long_description, classifiers=classifiers, keywords=['diagram','generator'], author='Takeshi Komiya', author_email='i.tkomiya at gmail.com', url='http://blockdiag.com/', download_url='http://pypi.python.org/pypi/seqdiag', license='Apache License 2.0', py_modules=['seqdiag_sphinxhelper'], packages=find_packages('src'), package_dir={'': 'src'}, package_data = {'': ['buildout.cfg']}, include_package_data=True, install_requires=[ 'setuptools', 'blockdiag>=1.3.0', # -*- Extra requirements: -*- ], extras_require=dict( test=test_requires, rst=[ 'docutils', ], ), test_suite='nose.collector', tests_require=test_requires, entry_points=""" [console_scripts] seqdiag = seqdiag.command:main """, ) seqdiag-0.9.0/examples/0000755000175000017500000000000012224000732016157 5ustar katsuwokatsuwo00000000000000seqdiag-0.9.0/examples/simple.diag0000644000175000017500000000042211546332373020313 0ustar katsuwokatsuwo00000000000000diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } seqdiag-0.9.0/examples/edge_type.diag0000644000175000017500000000074511546332373020777 0ustar katsuwokatsuwo00000000000000{ // normal edge A -> B [label = "normal edge"]; // dotted edge B --> C [label = "dotted edge"]; // asynchronus edge A ->> B [label = "asynchronus edge"]; B -->> C [label = "asynchronus dotted edge"]; // return edge B <- C [label = "return edge"]; A <-- B [label = "return dotted edge"]; B <<- C [label = "return asynchronus edge"]; A <<-- B [label = "return asynchronus dotted edge"]; // self referenced edge A -> A [label = "self referenced edge"]; } seqdiag-0.9.0/examples/edge_attributes.diag0000644000175000017500000000030311546332373022172 0ustar katsuwokatsuwo00000000000000{ // edge label A -> B [label = "call"]; A <- B [label = "return"]; // diagonal edge A -> B [diagonal, label = "diagonal edge"]; A <- B [diagonal, label = "return diagonal edge"]; } seqdiag-0.9.0/bootstrap.py0000644000175000017500000001306112216775473016757 0ustar katsuwokatsuwo00000000000000############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. """ import os import shutil import sys import tempfile from optparse import OptionParser tmpeggs = tempfile.mkdtemp() usage = '''\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] Bootstraps a buildout-based project. Simply run this script in a directory containing a buildout.cfg, using the Python that you want bin/buildout to use. Note that by using --find-links to point to local resources, you can keep this script from going over the network. ''' parser = OptionParser(usage=usage) parser.add_option("-v", "--version", help="use a specific zc.buildout version") parser.add_option("-t", "--accept-buildout-test-releases", dest='accept_buildout_test_releases', action="store_true", default=False, help=("Normally, if you do not specify a --version, the " "bootstrap script and buildout gets the newest " "*final* versions of zc.buildout and its recipes and " "extensions for you. If you use this flag, " "bootstrap and buildout will get the newest releases " "even if they are alphas or betas.")) parser.add_option("-c", "--config-file", help=("Specify the path to the buildout configuration " "file to be used.")) parser.add_option("-f", "--find-links", help=("Specify a URL to search for buildout releases")) options, args = parser.parse_args() ###################################################################### # load/install setuptools to_reload = False try: import pkg_resources import setuptools except ImportError: ez = {} try: from urllib.request import urlopen except ImportError: from urllib2 import urlopen # XXX use a more permanent ez_setup.py URL when available. exec(urlopen('http://bitbucket.org/pypa/setuptools/raw/0.7.2/ez_setup.py' ).read(), ez) setup_args = dict(to_dir=tmpeggs, download_delay=0) ez['use_setuptools'](**setup_args) if to_reload: reload(pkg_resources) import pkg_resources # This does not (always?) update the default working set. We will # do it. for path in sys.path: if path not in pkg_resources.working_set.entries: pkg_resources.working_set.add_entry(path) ###################################################################### # Install buildout ws = pkg_resources.working_set cmd = [sys.executable, '-c', 'from setuptools.command.easy_install import main; main()', '-mZqNxd', tmpeggs] find_links = os.environ.get( 'bootstrap-testing-find-links', options.find_links or ('http://downloads.buildout.org/' if options.accept_buildout_test_releases else None) ) if find_links: cmd.extend(['-f', find_links]) setuptools_path = ws.find( pkg_resources.Requirement.parse('setuptools')).location requirement = 'zc.buildout' version = options.version if version is None and not options.accept_buildout_test_releases: # Figure out the most recent final version of zc.buildout. import setuptools.package_index _final_parts = '*final-', '*final' def _final_version(parsed_version): for part in parsed_version: if (part[:1] == '*') and (part not in _final_parts): return False return True index = setuptools.package_index.PackageIndex( search_path=[setuptools_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) if index.obtain(req) is not None: best = [] bestv = None for dist in index[req.project_name]: distv = dist.parsed_version if _final_version(distv): if bestv is None or distv > bestv: best = [dist] bestv = distv elif distv == bestv: best.append(dist) if best: best.sort() version = best[-1].version if version: requirement = '=='.join((requirement, version)) cmd.append(requirement) import subprocess if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0: raise Exception( "Failed to execute command:\n%s", repr(cmd)[1:-1]) ###################################################################### # Import and run buildout ws.add_entry(tmpeggs) ws.require(requirement) import zc.buildout.buildout if not [a for a in args if '=' not in a]: args.append('bootstrap') # if -c was provided, we push it back into args for buildout' main function if options.config_file is not None: args[0:0] = ['-c', options.config_file] zc.buildout.buildout.main(args) shutil.rmtree(tmpeggs) seqdiag-0.9.0/src/0000755000175000017500000000000012224000732015130 5ustar katsuwokatsuwo00000000000000seqdiag-0.9.0/src/seqdiag.egg-info/0000755000175000017500000000000012224000732020237 5ustar katsuwokatsuwo00000000000000seqdiag-0.9.0/src/seqdiag.egg-info/PKG-INFO0000644000175000017500000002136412224000732021342 0ustar katsuwokatsuwo00000000000000Metadata-Version: 1.1 Name: seqdiag Version: 0.9.0 Summary: seqdiag generate sequence-diagram image file from spec-text file. Home-page: http://blockdiag.com/ Author: Takeshi Komiya Author-email: i.tkomiya at gmail.com License: Apache License 2.0 Download-URL: http://pypi.python.org/pypi/seqdiag Description: `seqdiag` generate sequence-diagram image file from spec-text file. Features ======== * Generate sequence-diagram from dot like text (basic feature). * Multilingualization for node-label (utf-8 only). You can get some examples and generated images on `blockdiag.com `_ . Setup ===== by easy_install ---------------- Make environment:: $ easy_install seqdiag by buildout ------------ Make environment:: $ hg clone http://bitbucket.org/tk0miya/seqdiag $ cd seqdiag $ python bootstrap.py $ bin/buildout Copy and modify ini file. example:: $ cp /blockdiag/examples/simple.diag . $ vi simple.diag Please refer to `spec-text setting sample`_ section for the format of the `simpla.diag` configuration file. spec-text setting sample ======================== Few examples are available. You can get more examples at `blockdiag.com `_ . simple.diag ------------ simple.diag is simply define nodes and transitions by dot-like text format:: diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } Usage ===== Execute seqdiag command:: $ seqdiag simple.diag $ ls simple.png simple.png Requirements ============ * Python 2.6, 2.7, 3.2, 3.3 * Pillow 2.2.1 * funcparserlib 0.3.6 * setuptools License ======= Apache License 2.0 History ======= 0.9.0 (2013-10-05) ------------------ * Support python 3.2 and 3.3 (thanks to @masayuko) * Drop supports for python 2.4 and 2.5 * Replace dependency: PIL -> Pillow 0.8.2 (2013-02-09) ------------------ * Fix bugs 0.8.1 (2012-11-12) ------------------ * Add altblock feature (experimental) * Fix bugs 0.8.0 (2012-10-22) ------------------ * Optimize algorithm for rendering shadow * Add options to docutils directive * Fix bugs 0.7.5 (2012-09-29) ------------------ * Fix bugs 0.7.4 (2012-09-20) ------------------ * Support blockdiag-1.1.7 interface * Fix bugs 0.7.3 (2012-03-16) ------------------ * Allow to insert separators in subedge-group * Fix bugs 0.7.2 (2011-12-12) ------------------ * Fix bugs 0.7.1 (2011-11-30) ------------------ * Fix bugs 0.7.0 (2011-11-19) ------------------ * Add fontfamily attribute for switching fontface * Fix bugs 0.6.3 (2011-11-06) ------------------ * Add docutils extention * Fix bugs 0.6.2 (2011-11-01) ------------------ * Add class feature (experimental) 0.6.1 (2011-11-01) ------------------ * Follow blockdiag-0.9.7 interface 0.6.0 (2011-10-28) ------------------ * Add edge attributes: note, rightnote, leftnote, notecolor * Add diagram atteribute: default_note_color 0.5.2 (2011-10-27) ------------------ * Implement auto edge height adjusting * Fix bugs 0.5.1 (2011-10-24) ------------------ * Fix bugs 0.5.0 (2011-10-21) ------------------ * Add diagram attributes: activation, autonumber * Add edge attribute: failed * Add separator syntax 0.4.3 (2011-10-19) ------------------ * Follow blockdiag-0.9.5 interface 0.4.2 (2011-10-11) ------------------ * Fix bugs 0.4.1 (2011-09-30) ------------------ * Add diagram attribute: default_text_color * Add node attribte: textcolor * Fix bugs 0.4.0 (2011-09-26) ------------------ * Add diagram attributes: default_node_color, default_group_color and default_line_color 0.3.8 (2011-08-02) ------------------ * Allow dot characters in node_id * Fix bugs 0.3.7 (2011-07-05) ------------------ * Fix bugs 0.3.6 (2011-07-03) ------------------ * Support input from stdin 0.3.5 (2011-06-02) ------------------ * Fix bugs 0.3.4 (2011-05-18) ------------------ * Fix bugs 0.3.3 (2011-05-16) ------------------ * Add --version option * Add sphinxhelper module 0.3.2 (2011-05-14) ------------------ * Render group label * Support blockdiag 0.8.1 core interface 0.3.1 (2011-04-22) ------------------ * Render group label * Fix sphinxcontrib_seqdiag does not work with seqdiag 0.3.0 0.3.0 (2011-04-22) ------------------ * Add group syntax 0.2.7 (2011-04-15) ------------------ * Adjust start coordinates of edges 0.2.6 (2011-04-14) ------------------ * Fix bugs * Allow unquoted utf8 characters 0.2.5 (2011-03-26) ------------------ * Fix seqdiag could not run under blockdiag 0.7.6 0.2.4 (2011-03-20) ------------------ * Fix bugs 0.2.3 (2011-03-09) ------------------ * Fix bugs 0.2.2 (2011-03-07) ------------------ * Fix could not run under python 2.4 * Support edge colors 0.2.1 (2011-02-28) ------------------ * Add default_shape attribute to diagram 0.2.0 (2011-02-27) ------------------ * Add metrix parameters for edge label: edge_height, edge_length * Fix bugs 0.1.7 (2011-01-21) ------------------ * Fix TeX exporting in Sphinx extension 0.1.6 (2011-01-15) ------------------ * Support blockdiag-0.6.3 * Fix bugs 0.1.5 (2011-01-15) ------------------ * Draw activity on lifelines * Support both direction edge with '=>' operator 0.1.4 (2011-01-13) ------------------ * Change synxtax around edges 0.1.3 (2011-01-12) ------------------ * Support diagonal edge * Fix bugs 0.1.2 (2011-01-11) ------------------ * Support nested edges * Add edge attributes; return, dir * Add sphinx extention module(sphinxcontrib_seqdiag) * Fix bugs 0.1.1 (2011-01-11) ------------------ * Fix bugs about layouting 0.1.0 (2011-01-08) ------------------ * first release Keywords: diagram,generator Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Documentation Classifier: Topic :: Text Processing :: Markup seqdiag-0.9.0/src/seqdiag.egg-info/dependency_links.txt0000644000175000017500000000000112224000732024305 0ustar katsuwokatsuwo00000000000000 seqdiag-0.9.0/src/seqdiag.egg-info/top_level.txt0000644000175000017500000000003512224000732022767 0ustar katsuwokatsuwo00000000000000seqdiag_sphinxhelper seqdiag seqdiag-0.9.0/src/seqdiag.egg-info/requires.txt0000644000175000017500000000010212224000732022630 0ustar katsuwokatsuwo00000000000000setuptools blockdiag>=1.3.0 [rst] docutils [test] Nose pep8>=1.3seqdiag-0.9.0/src/seqdiag.egg-info/SOURCES.txt0000644000175000017500000000145312224000732022126 0ustar katsuwokatsuwo00000000000000LICENSE MANIFEST.in bootstrap.py buildout.cfg seqdiag.1 setup.cfg setup.py examples/edge_attributes.diag examples/edge_type.diag examples/simple.diag src/README.txt src/seqdiag_sphinxhelper.py src/seqdiag/__init__.py src/seqdiag/builder.py src/seqdiag/command.py src/seqdiag/drawer.py src/seqdiag/elements.py src/seqdiag/metrics.py src/seqdiag/parser.py src/seqdiag.egg-info/PKG-INFO src/seqdiag.egg-info/SOURCES.txt src/seqdiag.egg-info/dependency_links.txt src/seqdiag.egg-info/entry_points.txt src/seqdiag.egg-info/requires.txt src/seqdiag.egg-info/top_level.txt src/seqdiag/tests/test_generate_diagram.py src/seqdiag/tests/test_pep8.py src/seqdiag/tests/test_rst_directives.py src/seqdiag/utils/__init__.py src/seqdiag/utils/rst/__init__.py src/seqdiag/utils/rst/directives.py src/seqdiag/utils/rst/nodes.pyseqdiag-0.9.0/src/seqdiag.egg-info/entry_points.txt0000644000175000017500000000010712224000732023533 0ustar katsuwokatsuwo00000000000000 [console_scripts] seqdiag = seqdiag.command:main seqdiag-0.9.0/src/seqdiag_sphinxhelper.py0000644000175000017500000000203612223737065021730 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'core', 'utils' ] import seqdiag import seqdiag.parser import seqdiag.builder import seqdiag.drawer core = seqdiag import seqdiag.utils.rst.nodes import seqdiag.utils.rst.directives utils = seqdiag.utils import blockdiag.utils.bootstrap utils.bootstrap = blockdiag.utils.bootstrap import blockdiag.utils.fontmap utils.fontmap = blockdiag.utils.fontmap import blockdiag.utils.compat utils.compat = blockdiag.utils.compat seqdiag-0.9.0/src/seqdiag/0000755000175000017500000000000012224000732016545 5ustar katsuwokatsuwo00000000000000seqdiag-0.9.0/src/seqdiag/builder.py0000644000175000017500000002006312217006633020556 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from seqdiag import parser from seqdiag.elements import (Diagram, DiagramNode, NodeGroup, DiagramEdge, EdgeSeparator, AltBlock) from blockdiag.utils import unquote, XY from blockdiag.utils.compat import u class DiagramTreeBuilder(object): def build(self, tree): self.diagram = Diagram() self.diagram = self.instantiate(self.diagram, None, tree) self.update_node_order() self.update_edge_order() self.update_altblock_ylevel() self.diagram.colwidth = len(self.diagram.nodes) self.diagram.colheight = len(self.diagram.edges) + 1 for sep in self.diagram.separators: self.diagram.edges.remove(sep) if self.diagram.activation != 'none': self.create_activities() if self.diagram.autonumber: self.update_label_numbered() return self.diagram def update_edge_order(self): for i, edge in enumerate(self.diagram.edges): edge.order = i height = len(self.diagram.edges) + 1 for group in self.diagram.groups: group.colheight = height def update_altblock_ylevel(self): altblocks = self.diagram.altblocks for i in range(len(self.diagram.edges) + 1): blocks = [b for b in altblocks if b.edges[0].order == i] for j, altblock in enumerate(reversed(blocks)): altblock.ylevel_top = j + 1 blocks = [b for b in altblocks if b.edges[-1].order == i] for j, altblock in enumerate(reversed(blocks)): altblock.ylevel_bottom = j + 1 def update_label_numbered(self): for i, edge in enumerate(self.diagram.edges): edge.label = u("%d. %s") % (i + 1, edge.label or "") def create_activities(self): if len(self.diagram.edges) == 0: return first_node = self.diagram.edges[0].node1 active_nodes = {first_node: 1} for node in self.diagram.nodes: if node.activated: active_nodes[node] = 1 edge_count = len(self.diagram.edges) + len(self.diagram.separators) for i in range(edge_count): match = [e for e in self.diagram.edges if e.order == i] if match: edge = match[0] if edge.node1 == edge.node2: pass elif edge.activate is False: pass elif edge.dir == 'forward': if edge.node2 in active_nodes: active_nodes[edge.node2] += 1 else: active_nodes[edge.node2] = 1 elif edge.dir == 'back': if edge.node2 in active_nodes: active_nodes[edge.node2] -= 1 else: active_nodes[edge.node2] = 0 for node in active_nodes: if active_nodes[node] > 0: for index in range(active_nodes[node]): node.activate(i, index) for node in self.diagram.nodes: node.deactivate() def update_node_order(self): x = 0 uniq = [] for node in self.diagram.nodes: if node not in uniq: node.xy = XY(x, 0) uniq.append(node) x += 1 if node.group: for subnode in node.group.nodes: if subnode not in uniq: subnode.xy = XY(x, 0) uniq.append(subnode) x += 1 for group in self.diagram.groups: x = min(node.xy.x for node in group.nodes) group.xy = XY(x, 0) group.colwidth = len(group.nodes) def append_node(self, node, group): if node not in self.diagram.nodes: self.diagram.nodes.append(node) if isinstance(group, NodeGroup) and node not in group.nodes: if node.group: msg = "DiagramNode could not belong to two groups" raise RuntimeError(msg) group.nodes.append(node) node.group = group def instantiate(self, group, block, tree): for stmt in tree.stmts: if isinstance(stmt, parser.Node): node = DiagramNode.get(stmt.id) node.set_attributes(stmt.attrs) self.append_node(node, group) elif isinstance(stmt, parser.Edge): self.instantiate_edge(group, block, stmt) elif isinstance(stmt, parser.SubGraph): node = NodeGroup.get(None) self.instantiate(node, block, stmt) self.diagram.groups.append(node) elif isinstance(stmt, parser.DefAttrs): if block: block.set_attributes(stmt.attrs) else: group.set_attributes(stmt.attrs) elif isinstance(stmt, parser.Separator): sep = EdgeSeparator(stmt.type, unquote(stmt.value)) sep.group = group self.diagram.separators.append(sep) group.edges.append(sep) elif isinstance(stmt, parser.AltBlock): subblock = AltBlock(stmt.type, stmt.id) if block: subblock.xlevel = block.xlevel + 1 self.diagram.altblocks.append(subblock) self.instantiate(group, subblock, stmt) if block: for edge in subblock.edges: block.edges.append(edge) elif isinstance(stmt, parser.AttrClass): name = unquote(stmt.name) Diagram.classes[name] = stmt elif isinstance(stmt, parser.AttrPlugin): self.diagram.set_plugin(stmt.name, stmt.attrs) return group def instantiate_edge(self, group, block, tree): node_id = tree.nodes[0] edge_from = DiagramNode.get(node_id) self.append_node(edge_from, group) edge_type, node_id = tree.nodes[1] edge_to = DiagramNode.get(node_id) self.append_node(edge_to, group) edge = DiagramEdge(edge_from, edge_to) if edge_type: edge.set_attributes([parser.Attr('dir', edge_type)]) edge.set_attributes(tree.attrs) if edge.dir in ('forward', 'both'): forward = edge.duplicate() forward.dir = 'forward' group.edges.append(forward) if block: block.edges.append(forward) if len(tree.nodes) > 2: nodes = [edge_to.id] + tree.nodes[2:] nested = parser.Edge(nodes, tree.attrs, tree.subedge) self.instantiate_edge(group, block, nested) elif tree.subedge: self.instantiate(group, block, tree.subedge) if edge.dir in ('back', 'both') and edge.node1 != edge.node2: reverse = edge.duplicate() reverse.dir = 'back' if edge.dir == 'both': reverse.style = 'dashed' reverse.label = edge.return_label reverse.leftnote = None reverse.rightnote = None group.edges.append(reverse) if block: block.edges.append(reverse) class ScreenNodeBuilder(object): @classmethod def build(cls, tree): DiagramNode.clear() DiagramEdge.clear() NodeGroup.clear() return DiagramTreeBuilder().build(tree) seqdiag-0.9.0/src/seqdiag/__init__.py0000644000175000017500000000117312223771043020671 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __version__ = '0.9.0' seqdiag-0.9.0/src/seqdiag/drawer.py0000644000175000017500000001477212216775473020444 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import blockdiag.drawer from seqdiag.metrics import DiagramMetrics from blockdiag.utils import XY class DiagramDraw(blockdiag.drawer.DiagramDraw): def create_metrics(self, *args, **kwargs): return DiagramMetrics(*args, **kwargs) def _draw_background(self): for node in self.nodes: node.activities.sort(key=lambda x: x['level']) if self.diagram.shadow_style != 'none': for node in self.nodes: for activity in node.activities: self.node_activity_shadow(node, activity) if self.diagram.shadow_style != 'none': for edge in self.edges: self.edge_shadow(edge) super(DiagramDraw, self)._draw_background() def _draw_elements(self, **kwargs): for block in self.diagram.altblocks: self.altblock(block) for node in self.nodes: self.lifelines(node) super(DiagramDraw, self)._draw_elements(**kwargs) for sep in self.diagram.separators: self.separator(sep) for group in self.diagram.groups: self.group_label(group, **kwargs) def node_activity_shadow(self, node, activity): box = self.metrics.activity_shadow(node, activity) if self.diagram.shadow_style == 'solid': self.drawer.rectangle(box, fill=self.shadow) else: self.drawer.rectangle(box, fill=self.shadow, filter='transp-blur') def node_activity(self, node, activity): box = self.metrics.activity_box(node, activity) self.drawer.rectangle(box, width=1, outline=self.diagram.linecolor, fill='moccasin') def lifelines(self, node): for line, style in self.metrics.lifeline(node): self.drawer.line(line, fill=self.diagram.linecolor, style=style) for activity in node.activities: self.node_activity(node, activity) def edge_shadow(self, edge): m = self.metrics dx, dy = m.shadow_offset if edge.leftnote: polygon = m.edge(edge).leftnoteshape shadow = [XY(pt.x + dx, pt.y + dy) for pt in polygon] if self.diagram.shadow_style == 'solid': self.drawer.polygon(shadow, fill=self.shadow, outline=self.shadow) else: self.drawer.polygon(shadow, fill=self.shadow, outline=self.shadow, filter='transp-blur') if edge.rightnote: polygon = m.edge(edge).rightnoteshape shadow = [XY(pt.x + dx, pt.y + dy) for pt in polygon] if self.diagram.shadow_style == 'solid': self.drawer.polygon(shadow, fill=self.shadow, outline=self.shadow) else: self.drawer.polygon(shadow, fill=self.shadow, outline=self.shadow, filter='transp-blur') def edge(self, edge): # render shaft of edges m = self.metrics.edge(edge) shaft = m.shaft self.drawer.line(shaft, fill=edge.color, style=edge.style) # render head of edges head = m.head if edge.async: self.drawer.line((head[0], head[1]), fill=edge.color) self.drawer.line((head[1], head[2]), fill=edge.color) else: self.drawer.polygon(head, outline=edge.color, fill=edge.color) if edge.failed: for line in m.failedmark: self.drawer.line(line, fill=edge.color) if edge.leftnote: polygon = m.leftnoteshape self.drawer.polygon(polygon, fill=edge.notecolor, outline=self.fill) folded = [polygon[1], XY(polygon[1].x, polygon[2].y), polygon[2]] self.drawer.line(folded, fill=self.fill) self.drawer.textarea(m.leftnotebox, edge.leftnote, self.metrics.font_for(edge), fill=edge.color, halign='left') if edge.rightnote: polygon = m.rightnoteshape self.drawer.polygon(polygon, fill=edge.notecolor, outline=self.fill) folded = [polygon[1], XY(polygon[1].x, polygon[2].y), polygon[2]] self.drawer.line(folded, fill=self.fill) self.drawer.textarea(m.rightnotebox, edge.rightnote, self.metrics.font_for(edge), fill=edge.color, halign='left') def edge_label(self, edge): m = self.metrics.edge(edge) if edge.label: if edge.direction in ('right', 'self'): halign = 'left' else: halign = 'right' self.drawer.textarea(m.textbox, edge.label, self.metrics.font_for(edge), fill=edge.color, halign=halign) def separator(self, sep): m = self.metrics.separator(sep) for line in m.lines: self.drawer.line(line, fill=self.fill, style=sep.style) if sep.type == 'delay': self.drawer.rectangle(m.labelbox, fill='white', outline='white') elif sep.type == 'divider': self.drawer.rectangle(m.labelbox, fill=sep.color, outline=sep.linecolor) self.drawer.textarea(m.labelbox, sep.label, self.metrics.font_for(sep), fill=sep.textcolor) def altblock(self, block): m = self.metrics.cell(block) self.drawer.rectangle(m, outline=block.linecolor) box = m.textbox line = [XY(box.x1, box.y2), XY(box.x2, box.y2), XY(box.x2 + self.metrics.cellsize * 2, box.y1)] self.drawer.line(line, fill=block.linecolor) self.drawer.textarea(box, block.type, fill=block.textcolor, font=self.metrics.font_for(block)) seqdiag-0.9.0/src/seqdiag/utils/0000755000175000017500000000000012224000732017705 5ustar katsuwokatsuwo00000000000000seqdiag-0.9.0/src/seqdiag/utils/__init__.py0000644000175000017500000000114411655372735022044 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. seqdiag-0.9.0/src/seqdiag/utils/rst/0000755000175000017500000000000012224000732020515 5ustar katsuwokatsuwo00000000000000seqdiag-0.9.0/src/seqdiag/utils/rst/directives.py0000644000175000017500000000716312223736264023256 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os from docutils import nodes from docutils.parsers import rst from seqdiag import parser from seqdiag.builder import ScreenNodeBuilder from seqdiag.drawer import DiagramDraw from seqdiag.utils.rst.nodes import seqdiag from blockdiag.utils.rst import directives directive_options_default = dict(format='PNG', antialias=False, fontpath=None, outputdir=None, nodoctype=False, noviewbox=False, inline_svg=False) directive_options = {} class SeqdiagDirectiveBase(directives.BlockdiagDirectiveBase): """ Directive to insert arbitrary dot markup. """ name = "seqdiag" node_class = seqdiag class SeqdiagDirective(directives.BlockdiagDirective): name = "seqdiag" node_class = seqdiag @property def global_options(self): return directive_options def node2diagram(self, node): tree = parser.parse_string(node['code']) return ScreenNodeBuilder.build(tree) def node2image(self, node, diagram): options = node['options'] filename = self.image_filename(node) fontmap = self.create_fontmap() _format = self.global_options['format'].lower() if _format == 'svg' and self.global_options['inline_svg'] is True: filename = None kwargs = dict(self.global_options) del kwargs['format'] drawer = DiagramDraw(_format, diagram, filename, fontmap=fontmap, **kwargs) if filename is None or not os.path.isfile(filename): drawer.draw() content = drawer.save(None) if _format == 'svg' and self.global_options['inline_svg'] is True: size = drawer.pagesize() if 'maxwidth' in options and options['maxwidth'] < size[0]: ratio = float(options['maxwidth']) / size[0] new_size = (options['maxwidth'], int(size[1] * ratio)) content = drawer.save(new_size) return nodes.raw('', content, format='html') size = drawer.pagesize() if 'maxwidth' in options and options['maxwidth'] < size[0]: ratio = float(options['maxwidth']) / size[0] thumb_size = (options['maxwidth'], size[1] * ratio) thumb_filename = self.image_filename(node, prefix='_thumb') if not os.path.isfile(thumb_filename): drawer.filename = thumb_filename drawer.draw() drawer.save(thumb_size) image = nodes.image(uri=thumb_filename, target=filename) else: image = nodes.image(uri=filename) if node['alt']: image['alt'] = node['alt'] return image def setup(**kwargs): for key, value in directive_options_default.items(): directive_options[key] = kwargs.get(key, value) rst.directives.register_directive("seqdiag", SeqdiagDirective) seqdiag-0.9.0/src/seqdiag/utils/rst/__init__.py0000644000175000017500000000114411655372724022652 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. seqdiag-0.9.0/src/seqdiag/utils/rst/nodes.py0000644000175000017500000000127012105450357022211 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from docutils import nodes class seqdiag(nodes.General, nodes.Element): pass seqdiag-0.9.0/src/seqdiag/parser.py0000644000175000017500000001610512223736264020435 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2008/2009 Andrey Vlasovskikh # # 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. r'''A DOT language parser using funcparserlib. The parser is based on [the DOT grammar][1]. It is pretty complete with a few not supported things: * Ports and compass points * XML identifiers At the moment, the parser builds only a parse tree, not an abstract syntax tree (AST) or an API for dealing with DOT. [1]: http://www.graphviz.org/doc/info/lang.html ''' import io from re import MULTILINE, DOTALL from collections import namedtuple from funcparserlib.lexer import make_tokenizer, Token, LexerError from funcparserlib.parser import (some, a, maybe, many, finished, skip, forward_decl) from blockdiag.utils.compat import u ENCODING = 'utf-8' Graph = namedtuple('Graph', 'type id stmts') SubGraph = namedtuple('SubGraph', 'stmts') Node = namedtuple('Node', 'id attrs') Attr = namedtuple('Attr', 'name value') Edge = namedtuple('Edge', 'nodes attrs subedge') DefAttrs = namedtuple('DefAttrs', 'object attrs') AttrClass = namedtuple('AttrClass', 'name attrs') AttrPlugin = namedtuple('AttrPlugin', 'name attrs') Separator = namedtuple('Separator', 'type value') AltBlock = namedtuple('AltBlock', 'type id stmts') class ParseException(Exception): pass def tokenize(string): """str -> Sequence(Token)""" specs = [ ('Comment', (r'/\*(.|[\r\n])*?\*/', MULTILINE)), ('Comment', (r'(//|#).*',)), ('NL', (r'[\r\n]+',)), ('Space', (r'[ \t\r\n]+',)), ('Separator', (r'(?P===|\.\.\.)[^\r\n]+(?P=sep)',)), ('Name', (u('[A-Za-z_0-9\u0080-\uffff]') + u('[A-Za-z_\\-.0-9\u0080-\uffff]*'),)), ('Op', (r'(=>)|[{};,=\[\]]|(<>?)',)), ('Number', (r'-?(\.[0-9]+)|([0-9]+(\.[0-9]*)?)',)), ('String', (r'(?P"|\').*?(? object""" unarg = lambda f: lambda args: f(*args) tokval = lambda x: x.value flatten = lambda list: sum(list, []) n = lambda s: a(Token('Name', s)) >> tokval op = lambda s: a(Token('Op', s)) >> tokval op_ = lambda s: skip(op(s)) _id = some(lambda t: t.type in ['Name', 'Number', 'String']).named('id') >> tokval sep = some(lambda t: t.type == 'Separator').named('sep') >> tokval make_graph_attr = lambda args: DefAttrs(u('graph'), [Attr(*args)]) make_edge = lambda x, x2, xs, attrs, subedge: \ Edge([x, x2] + xs, attrs, subedge) make_subedge = lambda args: SubGraph(args) make_separator = lambda s: Separator(s[0:3], s[3:-3].strip()) node_id = _id # + maybe(port) a_list = ( _id + maybe(op_('=') + _id) + skip(maybe(op(','))) >> unarg(Attr)) attr_list = ( many(op_('[') + many(a_list) + op_(']')) >> flatten) graph_attr = _id + op_('=') + _id >> make_graph_attr node_stmt = node_id + attr_list >> unarg(Node) separator_stmt = (sep >> make_separator) # edge statements:: # A -> B; # C -> D { # D -> E; # } # subedge = forward_decl() edge_rel = (op('<<--') | op('<--') | op('<<-') | op('<-') | op('->') | op('->>') | op('-->') | op('-->>') | op('=>')) edge_rhs = edge_rel + node_id edge_stmt = ( node_id + edge_rhs + many(edge_rhs) + attr_list + maybe(subedge) >> unarg(make_edge)) edge_stmt_list = many((edge_stmt | separator_stmt) + skip(maybe(op(';')))) subedge.define( op_('{') + edge_stmt_list + op_('}') >> make_subedge) # group statements:: # group { # A; # } # group_stmt = ( graph_attr | node_stmt ) group_stmt_list = many(group_stmt + skip(maybe(op(';')))) group = ( skip(n('group')) + skip(maybe(_id)) + op_('{') + group_stmt_list + op_('}') >> SubGraph) # alt statements:: # loop { # A -> B; # } # alt { # D -> E; # } # altblock = forward_decl() altblock_stmt = ( altblock | graph_attr | edge_stmt | node_stmt ) altblock_stmt_list = many(altblock_stmt + skip(maybe(op(';')))) alttypes = ( n('alt') | n('loop') ) altblock.define( alttypes + maybe(_id) + op_('{') + altblock_stmt_list + op_('}') >> unarg(AltBlock)) # # graph # class_stmt = ( skip(n('class')) + node_id + attr_list >> unarg(AttrClass)) plugin_stmt = ( skip(n('plugin')) + node_id + attr_list >> unarg(AttrPlugin)) stmt = ( altblock | group | class_stmt | plugin_stmt | edge_stmt | separator_stmt | graph_attr | node_stmt ) stmt_list = many(stmt + skip(maybe(op(';')))) graph = ( maybe(n('diagram') | n('seqdiag')) + maybe(_id) + op_('{') + stmt_list + op_('}') >> unarg(Graph)) dotfile = graph + skip(finished) return dotfile.parse(seq) def sort_tree(tree): def weight(node): if isinstance(node, (Attr, DefAttrs, AttrPlugin, AttrClass)): return 1 else: return 2 if hasattr(tree, 'stmts'): tree.stmts.sort(key=lambda x: weight(x)) for stmt in tree.stmts: sort_tree(stmt) return tree def parse_string(string): try: tree = parse(tokenize(string)) return sort_tree(tree) except LexerError as e: message = "Got unexpected token at line %d column %d" % e.place raise ParseException(message) except Exception as e: raise ParseException(str(e)) def parse_file(path): code = io.open(path, 'r', encoding='utf-8-sig').read() return parse_string(code) seqdiag-0.9.0/src/seqdiag/elements.py0000644000175000017500000001765012223736264020763 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import re import sys import blockdiag.elements from blockdiag.utils import images, Size, XY class NodeGroup(blockdiag.elements.NodeGroup): pass class DiagramNode(blockdiag.elements.DiagramNode): def __init__(self, _id): super(DiagramNode, self).__init__(_id) self.activated = False self.activity = [] self.activities = [] def set_activated(self, value): self.activated = True def activate(self, height, index): if len(self.activity) <= index: self.activity.insert(index, []) if (len(self.activity[index]) > 0 and (self.activity[index][-1] != height - 1)): self.deactivate(index) self.activity[index].append(height) def deactivate(self, index=None): if index is None: for i in range(len(self.activity)): self.deactivate(i) return if self.activity[index]: attr = {'lifetime': self.activity[index], 'level': index} self.activities.append(attr) self.activity[index] = [] class EdgeSeparator(blockdiag.elements.Base): basecolor = (208, 208, 208) linecolor = (0, 0, 0) @classmethod def clear(cls): super(EdgeSeparator, cls).clear() cls.basecolor = (208, 208, 208) cls.linecolor = (0, 0, 0) def __init__(self, _type, label): super(EdgeSeparator, self).__init__() self.label = label self.group = None self.style = None self.color = self.basecolor self.order = 0 if _type == '===': self.type = 'divider' elif _type == '...': self.type = 'delay' class DiagramEdge(blockdiag.elements.DiagramEdge): notecolor = (255, 182, 193) # LightPink @classmethod def clear(cls): super(DiagramEdge, cls).clear() cls.notecolor = (255, 182, 193) @classmethod def set_default_note_color(cls, color): color = images.color_to_rgb(color) cls.notecolor = color def __init__(self, node1, node2): super(DiagramEdge, self).__init__(node1, node2) self.leftnote = None self.leftnotesize = Size(0, 0) self.rightnote = None self.rightnotesize = Size(0, 0) self.textwidth = 0 self.textheight = 0 self.order = 0 self.activate = True self.async = False self.diagonal = False self.failed = False self.return_label = '' @property def left_node(self): if self.node1.xy.x <= self.node2.xy.x: return self.node1 else: return self.node2 @property def right_node(self): if self.node1.xy.x > self.node2.xy.x: return self.node1 else: return self.node2 @property def direction(self): if self.node1.xy.x == self.node2.xy.x: direction = 'self' elif self.node1.xy.x < self.node2.xy.x: # n1 .. n2 if self.dir == 'forward': direction = 'right' else: direction = 'left' else: # n2 .. n1 if self.dir == 'forward': direction = 'left' else: direction = 'right' return direction def set_note(self, value): self.rightnote = value def set_diagonal(self, value): self.diagonal = True def set_async(self, value): self.dir = 'forward' def set_return(self, value): self.return_label = value def set_failed(self, value): self.failed = True self.activate = False def set_activate(self, value): self.activate = True def set_noactivate(self, value): self.activate = False def set_dir(self, value): _dir = value.lower() if _dir in ('back', 'both', 'forward'): self.dir = _dir elif _dir == '=>': self.dir = 'both' elif _dir in ('->', '->>', '-->', '-->>'): self.dir = 'forward' if re.search('--', _dir): self.style = 'dashed' else: self.style = None if re.search('>>', _dir): self.async = True else: self.async = False elif _dir in ('<-', '<<-', '<--', '<<--'): self.dir = 'back' if re.search('--', _dir): self.style = 'dashed' else: self.style = None if re.search('<<', _dir): self.async = True else: self.async = False else: msg = "WARNING: unknown edge dir: %s\n" % _dir sys.stderr.write(msg) class AltBlock(blockdiag.elements.Base): basecolor = (0, 0, 0) linecolor = (0, 0, 0) width = None height = None @classmethod def clear(cls): super(EdgeSeparator, cls).clear() cls.basecolor = (0, 0, 0) cls.linecolor = (0, 0, 0) @classmethod def set_default_linecolor(cls, color): color = images.color_to_rgb(color) cls.linecolor = color def __init__(self, _type, _id): self.type = _type self.id = _id self.xlevel = 1 self.ylevel_top = 1 self.ylevel_bottom = 1 self.edges = [] self.color = self.basecolor @property def xy(self): if len(self.edges) == 0: return XY(0, 0) else: x = min(e.left_node.xy.x for e in self.edges) y = min(e.order for e in self.edges) + 1 return XY(x, y) @property def colwidth(self): if len(self.edges) == 0: return 1 else: x2 = max(e.right_node.xy.x for e in self.edges) return x2 - self.xy.x + 1 @property def colheight(self): if len(self.edges) == 0: return 1 else: y2 = max(e.order for e in self.edges) + 1 return y2 - self.xy.y + 1 class Diagram(blockdiag.elements.Diagram): _DiagramNode = DiagramNode _DiagramEdge = DiagramEdge def __init__(self): super(Diagram, self).__init__() self.int_attrs.append('edge_length') self.activation = True self.autonumber = False self.edge_length = None self.groups = [] self.separators = [] self.altblocks = [] def traverse_groups(self, preorder=False): return self.groups def set_default_linecolor(self, color): super(Diagram, self).set_default_linecolor(color) color = images.color_to_rgb(color) AltBlock.set_default_linecolor(color) def set_default_note_color(self, color): color = images.color_to_rgb(color) self._DiagramEdge.set_default_note_color(color) def set_activation(self, value): value = value.lower() if value == 'none': self.activation = value else: msg = "WARNING: unknown activation style: %s\n" % value sys.stderr.write(msg) def set_autonumber(self, value): if value.lower() == 'false': self.autonumber = False else: self.autonumber = True def set_edge_height(self, value): msg = "WARNING: edge_height is obsoleted; use span_height\n" sys.stderr.write(msg) self.span_height = int(value) seqdiag-0.9.0/src/seqdiag/metrics.py0000644000175000017500000004472112217024524020604 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import division import sys from collections import namedtuple, defaultdict from seqdiag import elements import blockdiag.metrics from blockdiag.utils import Box, XY class DiagramMetrics(blockdiag.metrics.DiagramMetrics): edge_height = 10 def __init__(self, diagram, **kwargs): super(DiagramMetrics, self).__init__(diagram, **kwargs) self.node_count = len(diagram.nodes) self.edges = diagram.edges self.separators = diagram.separators self.page_padding = [0, 0, self.cellsize * 3, 0] if diagram.edge_length: span_width = diagram.edge_length - self.node_width if span_width < 0: msg = "WARNING: edge_length is too short: %d\n" % \ diagram.edge_length sys.stderr.write(msg) span_width = 0 self.spreadsheet.set_span_width(0, self.span_width) self.spreadsheet.set_span_width(self.node_count, self.span_width) self.span_width = span_width for edge in diagram.edges: edge.textwidth, edge.textheight = self.edge_textsize(edge) height = self.edge_height + edge.textheight if edge.diagonal: height += self.node_height * 3 // 4 elif edge.direction == 'self': height += self.cellsize * 2 font = self.font_for(edge) if edge.leftnote: edge.leftnotesize = self.textsize(edge.leftnote, font=font) if height < edge.leftnotesize.height: height = edge.leftnotesize.height if edge.rightnote: edge.rightnotesize = self.textsize(edge.rightnote, font=font) if height < edge.rightnotesize.height: height = edge.rightnotesize.height self.spreadsheet.set_node_height(edge.order + 1, height) self.expand_pagesize_for_note(edge) span_width = defaultdict(int) span_height = defaultdict(int) for block in diagram.altblocks: x1, y1 = block.xy x2 = x1 + block.colwidth y2 = y1 + block.colheight for y in range(y1, y2): span_width[(x1, y)] += 1 span_width[(x2, y)] += 1 for x in range(x1, x2): if block.type != 'else': span_height[(x, y1)] += 1 span_height[(x, y2)] += 1 for x in range(self.node_count + 1): widths = [span_width[xy] for xy in span_width if xy[0] == x] if widths: width = self.span_width + max(widths) * self.cellsize self.spreadsheet.set_span_width(x, width) for y in range(0, len(self.edges) + 1): blocks = [b for b in diagram.altblocks if b.edges[0].order == y] span_height = self.spreadsheet.span_height[y] span_height = 0 if blocks: max_ylevel_top = max(b.ylevel_top for b in blocks) span_height = (self.spreadsheet.span_height[y + 1] + self.cellsize * 5 // 2 * (max_ylevel_top - 1) + self.cellsize) self.spreadsheet.set_span_height(y + 1, span_height) blocks = [b for b in diagram.altblocks if b.edges[-1].order == y] if blocks: max_ylevel_bottom = max(b.ylevel_bottom for b in blocks) span_height = (self.spreadsheet.span_height[y + 2] + self.cellsize // 2 * (max_ylevel_bottom - 1)) self.spreadsheet.set_span_height(y + 2, span_height) def pagesize(self, width=None, height=None): width = self.node_count height = len(self.edges) + len(self.separators) + 1 return super(DiagramMetrics, self).pagesize(width, height) @property def bottomheight(self): height = len(self.edges) + len(self.separators) dummy = elements.DiagramNode(None) dummy.xy = XY(1, height) _, y = self.spreadsheet._node_bottomright(dummy, use_padding=False) y += self.spreadsheet.span_height[len(self.edges) + 1] // 2 return y @property def edge_length(self): return self.node_width + self.span_width def lifeline(self, node): delayed = [] for sep in self.separators: if sep.type == 'delay': delayed.append(sep) lines = [] d = self.cellsize pt = self.node(node).bottom for sep in delayed: m = self.cell(sep) y1 = m.top.y y2 = m.bottom.y lines.append(((pt, XY(pt.x, y1)), '8,4')) lines.append(((XY(pt.x, y1 + d), XY(pt.x, y2 - d)), '2,8')) pt = XY(pt.x, y2) y = self.bottomheight + self.cellsize * 4 lines.append(((pt, XY(pt.x, y)), '8,4')) return lines def activity_box(self, node, activity): edges = dict([e.order, e] for e in self.edges + self.separators) # y coodinates for top of activity box starts = activity['lifetime'][0] edge = edges[starts] y1 = self.edge(edge).baseheight if isinstance(edge, elements.DiagramEdge): if edge.diagonal and edge.node2 == node: y1 += self.edge_height * 3 // 4 # y coodinates for bottom of activity box ends = activity['lifetime'][-1] + 1 if ends < len(edges): y2 = self.edge(edges[ends]).baseheight else: y2 = self.bottomheight + self.cellsize * 2 index = activity['level'] base_x = self.cell(node).bottom.x box = Box(base_x + (index - 1) * self.cellsize // 2, y1, base_x + (index + 1) * self.cellsize // 2, y2) return box def activity_shadow(self, node, activity): box = self.activity_box(node, activity) return Box(box[0] + self.shadow_offset.x, box[1] + self.shadow_offset.y, box[2] + self.shadow_offset.x, box[3] + self.shadow_offset.y) def edge_textsize(self, edge): width = 0 height = 0 if edge.label: if edge.direction == 'self': cell = self.cell(edge.node1) width = self.edge(edge).right - cell.center.x else: width = (self.cell(edge.right_node).center.x - self.cell(edge.left_node).center.x - self.cellsize * 4) # 4: width of activity and padding width, height = self.textsize(edge.label, width=width, font=self.font_for(edge)) return XY(width, height) def expand_pagesize_for_note(self, edge): if edge.leftnote: cell = self.cell(edge.left_node) width = cell.center.x - self.cellsize * 6 if width < edge.leftnotesize.width: span_width = edge.leftnotesize.width - width self.spreadsheet.span_width[0] += span_width if edge.rightnote: cell = self.cell(edge.right_node) if edge.direction == 'self': right = self.edge(edge).right width = self.pagesize().x - right - self.cellsize * 3 else: width = self.pagesize().x - cell.center.x - self.cellsize * 3 if edge.right_node.xy.x + 1 == self.node_count: width -= self.cellsize * 2 if width < edge.rightnotesize.width: span_width = edge.rightnotesize.width - width self.spreadsheet.span_width[self.node_count] += span_width def cell(self, obj, use_padding=True): if isinstance(obj, (elements.DiagramEdge, elements.EdgeSeparator)): klass = namedtuple('_', 'xy width height colwidth colheight') edge = klass(XY(1, obj.order + 1), None, None, 1, 1) return super(DiagramMetrics, self).cell(edge, use_padding=False) elif isinstance(obj, elements.AltBlock): box = super(DiagramMetrics, self).cell(obj, use_padding=False) return AltBlockMetrics(self, obj, box) else: return super(DiagramMetrics, self).cell(obj, use_padding) def edge(self, edge): if isinstance(edge, elements.EdgeSeparator): return self.separator(edge) else: return EdgeMetrics(edge, self) def separator(self, separator): return SeparatorMetrics(separator, self) class AltBlockMetrics(blockdiag.metrics.NodeMetrics): def __init__(self, metrics, block, node): self.block = block sheet = metrics.spreadsheet cellsize = metrics.cellsize box = node.box box[0] -= (sheet.span_width[block.xy.x + 1] // 2 - cellsize * (block.xlevel - 1)) box[1] -= cellsize * 5 // 2 * (block.ylevel_top - 1) + cellsize * 3 box[2] += (sheet.span_width[block.xy.x + block.colwidth + 2] // 2 - cellsize * (block.xlevel - 1)) box[3] += cellsize * (block.ylevel_bottom - 1) + cellsize super(AltBlockMetrics, self).__init__(metrics, *box) @property def textbox(self): size = self.metrics.textsize(self.block.type, font=self.metrics.font_for(self.block)) return Box(self.x1, self.y1, self.x1 + size.width, self.y1 + size.height) class EdgeMetrics(object): def __init__(self, edge, metrics): self.metrics = metrics self.edge = edge @property def baseheight(self): cell = self.metrics.cell(self.edge) if (cell.height == self.edge.leftnotesize.height or (cell.height == self.edge.rightnotesize.height)): return cell.center.y else: return cell.top.y + self.edge.textheight @property def right(self): m = self.metrics cell = m.cell(self.edge.right_node) if self.edge.direction == 'self': if self.edge.node1.xy.x + 1 == m.node_count: width = cell.width // 2 + m.cellsize * 3 else: span_width = m.spreadsheet.span_width[self.edge.node1.xy.x] width = cell.width // 2 + span_width // 2 x = cell.bottom.x + width else: x = cell.bottom.x - m.cellsize if self.edge.failed: x -= self.metrics.edge_length // 2 return x @property def shaft(self): m = self.metrics baseheight = self.baseheight if self.edge.direction == 'self': cell = m.cell(self.edge.node1) fold_height = m.cellsize * 2 # adjust textbox to right on activity-lines base_x = cell.bottom.x x1 = base_x + self.activity_line_width(self.edge.node1) x2 = self.right line = [XY(x1 + m.cellsize, baseheight), XY(x2, baseheight), XY(x2, baseheight + fold_height), XY(x1 + m.cellsize, baseheight + fold_height)] else: x1 = (self.metrics.node(self.edge.left_node).bottom.x + self.activity_line_width(self.edge.left_node)) x2 = self.metrics.node(self.edge.right_node).bottom.x margin = m.cellsize if self.edge.diagonal: height = m.node_height * 3 // 4 if self.edge.direction == 'right': line = [XY(x1 + margin, baseheight), XY(x2 - margin, baseheight + height)] else: line = [XY(x1 + margin, baseheight + height), XY(x2 - margin, baseheight)] else: line = [XY(x1 + margin, baseheight), XY(x2 - margin, baseheight)] if self.edge.failed: edge_length = self.metrics.edge_length pt1, pt2 = line if self.edge.direction == 'right': pt2 = XY(pt2.x - edge_length // 2, (pt1.y + pt2.y) // 2) else: pt1 = XY(pt1.x + edge_length // 2, (pt1.y + pt2.y) // 2) line = [pt1, pt2] return line @property def failedmark(self): lines = [] if self.edge.failed: r = self.metrics.cellsize if self.edge.direction == 'right': pt = self.shaft[-1] lines.append((XY(pt.x + r, pt.y - r), XY(pt.x + r * 3, pt.y + r))) lines.append((XY(pt.x + r, pt.y + r), XY(pt.x + r * 3, pt.y - r))) else: pt = self.shaft[0] lines.append((XY(pt.x - r * 3, pt.y - r), XY(pt.x - r, pt.y + r))) lines.append((XY(pt.x - r * 3, pt.y + r), XY(pt.x - r, pt.y - r))) return lines @property def head(self): cell = self.metrics.cellsize head = [] if self.edge.direction == 'right': xy = self.shaft[-1] head.append(XY(xy.x - cell, xy.y - cell // 2)) head.append(xy) head.append(XY(xy.x - cell, xy.y + cell // 2)) elif self.edge.direction == 'left': xy = self.shaft[0] head.append(XY(xy.x + cell, xy.y - cell // 2)) head.append(xy) head.append(XY(xy.x + cell, xy.y + cell // 2)) else: # self xy = self.shaft[-1] head.append(XY(xy.x + cell, xy.y - cell // 2)) head.append(xy) head.append(XY(xy.x + cell, xy.y + cell // 2)) return head @property def textbox(self): m = self.metrics if self.edge.direction == 'self': x = m.node(self.edge.node1).bottom.x + \ self.activity_line_width(self.edge.node1) elif self.edge.direction == 'right': x = m.node(self.edge.left_node).bottom.x + \ self.activity_line_width(self.edge.left_node) + \ self.metrics.cellsize // 2 else: # left x = m.node(self.edge.right_node).bottom.x - self.edge.textwidth y1 = self.baseheight - self.edge.textheight return Box(x, y1, x + self.edge.textwidth, y1 + self.edge.textheight) def activity_line_width(self, node): m = self.metrics index = self.edge.order activities = [a for a in node.activities if index in a['lifetime']] if activities: level = max(a['level'] for a in activities) else: level = 0 return m.cellsize // 2 * level @property def leftnotebox(self): if not self.edge.leftnote: return Box(0, 0, 0, 0) m = self.metrics cell = m.cell(self.edge.left_node) notesize = self.edge.leftnotesize x = cell.center.x - m.cellsize * 3 - notesize.width y = self.baseheight - notesize.height // 2 if self.edge.failed and self.edge.direction == 'left': x += self.metrics.edge_length // 2 - m.cellsize return Box(x, y, x + notesize.width, y + notesize.height) @property def leftnoteshape(self): if not self.edge.leftnote: return [] r = self.metrics.cellsize box = self.leftnotebox return [XY(box[0], box[1]), XY(box[2], box[1]), XY(box[2] + r, box[1] + r), XY(box[2] + r, box[3]), XY(box[0], box[3]), XY(box[0], box[1])] @property def rightnotebox(self): if not self.edge.rightnote: return Box(0, 0, 0, 0) m = self.metrics cell = m.cell(self.edge.right_node) if self.edge.direction == 'self': x = self.right + m.cellsize * 2 elif self.edge.failed and self.edge.direction == 'right': x = self.right + m.cellsize * 4 else: x = cell.center.x + m.cellsize * 2 notesize = self.edge.rightnotesize y = self.baseheight - notesize.height // 2 return Box(x, y, x + notesize.width, y + notesize.height) @property def rightnoteshape(self): if not self.edge.rightnote: return [] r = self.metrics.cellsize box = self.rightnotebox return [XY(box[0], box[1]), XY(box[2], box[1]), XY(box[2] + r, box[1] + r), XY(box[2] + r, box[3]), XY(box[0], box[3]), XY(box[0], box[1])] class SeparatorMetrics(object): def __init__(self, separator, metrics): self.metrics = metrics self.separator = separator x1, x2 = self.baseline y1 = self.baseheight y2 = y1 + self.metrics.node_height d = self.metrics.cellsize // 4 font = metrics.font_for(self) size = metrics.textsize(separator.label, font, x2 - x1) dx = (x2 - x1 - size.width) // 2 dy = (y2 - y1 - size.height) // 2 self.labelbox = Box(x1 + dx - d, y1 + dy - d, x1 + dx + size.width + d, y1 + dy + size.height + d) @property def baseheight(self): return self.metrics.cell(self.separator).top.y @property def baseline(self): dummy = elements.DiagramNode(None) dummy.xy = XY(0, 1) dummy.colwidth = self.metrics.node_count m = self.metrics.cell(dummy) r = self.metrics.cellsize * 3 return (m.x1 - r, m.x2 + r) @property def lines(self): lines = [] if self.separator.type == 'divider': y = (self.labelbox[1] + self.labelbox[3]) // 2 x1, x2 = self.baseline d = self.metrics.cellsize // 4 lines.append((XY(x1, y - d), XY(self.labelbox[0], y - d))) lines.append((XY(x1, y + d), XY(self.labelbox[0], y + d))) lines.append((XY(self.labelbox[2], y - d), XY(x2, y - d))) lines.append((XY(self.labelbox[2], y + d), XY(x2, y + d))) return lines seqdiag-0.9.0/src/seqdiag/tests/0000755000175000017500000000000012224000732017707 5ustar katsuwokatsuwo00000000000000seqdiag-0.9.0/src/seqdiag/tests/test_rst_directives.py0000644000175000017500000006007312223736264024376 0ustar katsuwokatsuwo00000000000000# -*- coding: utf-8 -*- import sys if sys.version_info < (2, 7): import unittest2 as unittest else: import unittest import os import io import tempfile from blockdiag.tests.utils import stderr_wrapper, with_pil from docutils import nodes from docutils.core import publish_doctree, publish_parts from docutils.parsers.rst import directives as docutils from seqdiag.utils.rst import directives class TestRstDirectives(unittest.TestCase): def setUp(self): docutils.register_directive('seqdiag', directives.SeqdiagDirectiveBase) self.tmpdir = tempfile.mkdtemp() def tearDown(self): if 'seqdiag' in docutils._directives: del docutils._directives['seqdiag'] for filename in os.listdir(self.tmpdir): os.unlink(self.tmpdir + "/" + filename) os.rmdir(self.tmpdir) def test_setup(self): directives.setup() options = directives.directive_options self.assertIn('seqdiag', docutils._directives) self.assertEqual(directives.SeqdiagDirective, docutils._directives['seqdiag']) self.assertEqual('PNG', options['format']) self.assertEqual(False, options['antialias']) self.assertEqual(None, options['fontpath']) self.assertEqual(False, options['nodoctype']) self.assertEqual(False, options['noviewbox']) self.assertEqual(False, options['inline_svg']) def test_setup_with_args(self): directives.setup(format='SVG', antialias=True, fontpath='/dev/null', nodoctype=True, noviewbox=True, inline_svg=True) options = directives.directive_options self.assertIn('seqdiag', docutils._directives) self.assertEqual(directives.SeqdiagDirective, docutils._directives['seqdiag']) self.assertEqual('SVG', options['format']) self.assertEqual(True, options['antialias']) self.assertEqual('/dev/null', options['fontpath']) self.assertEqual(True, options['nodoctype']) self.assertEqual(True, options['noviewbox']) self.assertEqual(True, options['inline_svg']) @stderr_wrapper def test_base_noargs(self): text = ".. seqdiag::" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.system_message, type(doctree[0])) def test_base_with_block(self): text = ".. seqdiag::\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(directives.seqdiag, type(doctree[0])) self.assertEqual('{ A -> B }', doctree[0]['code']) self.assertEqual(None, doctree[0]['alt']) self.assertEqual({}, doctree[0]['options']) @stderr_wrapper def test_base_with_emptyblock(self): text = ".. seqdiag::\n\n \n" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.system_message, type(doctree[0])) def test_base_with_filename(self): dirname = os.path.dirname(__file__) filename = os.path.join(dirname, 'diagrams/node_notes.diag') text = ".. seqdiag:: %s" % filename doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(directives.seqdiag, type(doctree[0])) self.assertEqual(io.open(filename).read(), doctree[0]['code']) self.assertEqual(None, doctree[0]['alt']) self.assertEqual({}, doctree[0]['options']) @stderr_wrapper def test_base_with_filename_not_exists(self): text = ".. seqdiag:: unknown.diag" doctree = publish_doctree(text) self.assertEqual(nodes.system_message, type(doctree[0])) @stderr_wrapper def test_base_with_block_and_filename(self): text = ".. seqdiag:: unknown.diag\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.system_message, type(doctree[0])) def test_base_with_options(self): text = ".. seqdiag::\n :alt: hello world\n :desctable:\n" + \ " :maxwidth: 100\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(directives.seqdiag, type(doctree[0])) self.assertEqual('{ A -> B }', doctree[0]['code']) self.assertEqual('hello world', doctree[0]['alt']) self.assertEqual(None, doctree[0]['options']['desctable']) self.assertEqual(100, doctree[0]['options']['maxwidth']) def test_block(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertFalse('alt' in doctree[0]) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) self.assertFalse('target' in doctree[0]) def test_block_alt(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n :alt: hello world\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual('hello world', doctree[0]['alt']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) self.assertFalse('target' in doctree[0]) def test_block_fontpath1(self): with self.assertRaises(RuntimeError): directives.setup(format='SVG', fontpath=['dummy.ttf'], outputdir=self.tmpdir) text = ".. seqdiag::\n :alt: hello world\n\n { A -> B }" publish_doctree(text) def test_block_fontpath2(self): with self.assertRaises(RuntimeError): directives.setup(format='SVG', fontpath='dummy.ttf', outputdir=self.tmpdir) text = ".. seqdiag::\n :alt: hello world\n\n { A -> B }" publish_doctree(text) def test_caption(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n :caption: hello world\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.figure, type(doctree[0])) self.assertEqual(2, len(doctree[0])) self.assertEqual(nodes.image, type(doctree[0][0])) self.assertEqual(nodes.caption, type(doctree[0][1])) self.assertEqual(1, len(doctree[0][1])) self.assertEqual(nodes.Text, type(doctree[0][1][0])) self.assertEqual('hello world', doctree[0][1][0]) def test_block_maxwidth(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n :maxwidth: 100\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertFalse('alt' in doctree[0]) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) self.assertFalse(0, doctree[0]['target'].index(self.tmpdir)) def test_block_nodoctype_false(self): directives.setup(format='SVG', outputdir=self.tmpdir, nodoctype=False) text = ".. seqdiag::\n :alt: hello world\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) svg = open(doctree[0]['uri']).read() self.assertEqual("\n" " B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[-1])) svg = open(doctree[0]['uri']).read() self.assertNotEqual("\n" " B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) svg = open(doctree[0]['uri']).read() self.assertRegexpMatches(svg, '\n" " B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) def test_block_inline_svg_true_with_multibytes(self): directives.setup(format='SVG', outputdir=self.tmpdir, inline_svg=True) text = ".. seqdiag::\n :alt: hello world\n\n { あ -> い }" publish_parts(text) def test_block_max_width_inline_svg(self): directives.setup(format='SVG', outputdir=self.tmpdir, nodoctype=True, noviewbox=True, inline_svg=True) text = ".. seqdiag::\n :maxwidth: 100\n\n { A -> B }" doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.raw, type(doctree[0])) self.assertEqual(nodes.Text, type(doctree[0][0])) self.assertRegexpMatches(doctree[0][0], ' B; }" doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) self.assertEqual(1, len(doctree[1])) self.assertEqual(nodes.tgroup, type(doctree[1][0])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(0, len(doctree[1][0][0])) self.assertEqual(50, doctree[1][0][0]['colwidth']) self.assertEqual(0, len(doctree[1][0][1])) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(1, len(thead)) self.assertEqual(2, len(thead[0])) self.assertEqual(1, len(thead[0][0])) self.assertEqual(1, len(thead[0][0][0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual(1, len(thead[0][1])) self.assertEqual(1, len(thead[0][1][0])) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual(2, len(tbody[0])) self.assertEqual(1, len(tbody[0][0])) self.assertEqual(1, len(tbody[0][0][0])) self.assertEqual('A', tbody[0][0][0][0]) self.assertEqual(1, len(tbody[0][1])) self.assertEqual('foo', tbody[0][1][0][0]) self.assertEqual(2, len(tbody[1])) self.assertEqual(1, len(tbody[1][0])) self.assertEqual(1, len(tbody[1][0][0])) self.assertEqual('B', tbody[1][0][0][0]) self.assertEqual(1, len(tbody[1][1])) self.assertEqual('bar', tbody[1][1][0][0]) def test_desctable_with_rest_markups(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n :desctable:\n\n" + \ " { A [description = \"foo *bar* **baz**\"]; " + \ " B [description = \"**foo** *bar* baz\"]; }" doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(50, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('A', tbody[0][0][0][0]) self.assertEqual(4, len(tbody[0][1][0])) self.assertEqual(nodes.Text, type(tbody[0][1][0][0])) self.assertEqual('foo ', str(tbody[0][1][0][0])) self.assertEqual(nodes.emphasis, type(tbody[0][1][0][1])) self.assertEqual(nodes.Text, type(tbody[0][1][0][1][0])) self.assertEqual('bar', tbody[0][1][0][1][0]) self.assertEqual(nodes.Text, type(tbody[0][1][0][2])) self.assertEqual(' ', str(tbody[0][1][0][2])) self.assertEqual(nodes.strong, type(tbody[0][1][0][3])) self.assertEqual(nodes.Text, type(tbody[0][1][0][3][0])) self.assertEqual('baz', str(tbody[0][1][0][3][0])) self.assertEqual('B', tbody[1][0][0][0]) self.assertEqual(4, len(tbody[1][1][0])) self.assertEqual(nodes.strong, type(tbody[1][1][0][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][0][0])) self.assertEqual('foo', str(tbody[1][1][0][0][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][1])) self.assertEqual(' ', str(tbody[1][1][0][1])) self.assertEqual(nodes.emphasis, type(tbody[1][1][0][2])) self.assertEqual(nodes.Text, type(tbody[1][1][0][2][0])) self.assertEqual('bar', str(tbody[1][1][0][2][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][3])) self.assertEqual(' baz', str(tbody[1][1][0][3])) def test_desctable_with_numbered(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n :desctable:\n\n" + \ " { A [numbered = 2]; B [numbered = 1]; }" doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(25, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('No', thead[0][0][0][0]) self.assertEqual('Name', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('1', tbody[0][0][0][0]) self.assertEqual('B', tbody[0][1][0][0]) self.assertEqual('2', tbody[1][0][0][0]) self.assertEqual('A', tbody[1][1][0][0]) def test_desctable_with_numbered_and_description(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n :desctable:\n\n" + \ " { A [description = foo, numbered = 2]; " + \ " B [description = bar, numbered = 1]; }" doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(5, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.colspec, type(doctree[1][0][2])) self.assertEqual(nodes.thead, type(doctree[1][0][3])) self.assertEqual(nodes.tbody, type(doctree[1][0][4])) # colspec self.assertEqual(25, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) self.assertEqual(50, doctree[1][0][2]['colwidth']) # thead thead = doctree[1][0][3] self.assertEqual(3, len(thead[0])) self.assertEqual('No', thead[0][0][0][0]) self.assertEqual('Name', thead[0][1][0][0]) self.assertEqual('Description', thead[0][2][0][0]) # tbody tbody = doctree[1][0][4] self.assertEqual(2, len(tbody)) self.assertEqual('1', tbody[0][0][0][0]) self.assertEqual('B', tbody[0][1][0][0]) self.assertEqual(1, len(tbody[0][2])) self.assertEqual('bar', tbody[0][2][0][0]) self.assertEqual('2', tbody[1][0][0][0]) self.assertEqual('A', tbody[1][1][0][0]) self.assertEqual('foo', tbody[1][2][0][0]) def test_desctable_for_edges(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n :desctable:\n\n" + \ " { A -> B [description = \"foo\"]; " + \ " C -> D [description = \"bar\"]; " + \ " C [label = \"label_C\"]; " + \ " D [label = \"label_D\"]; }" doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(25, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('A -> B', tbody[0][0][0][0]) self.assertEqual(1, len(tbody[0][1][0])) self.assertEqual(nodes.Text, type(tbody[0][1][0][0])) self.assertEqual('foo', str(tbody[0][1][0][0])) self.assertEqual('label_C -> label_D', tbody[1][0][0][0]) self.assertEqual(1, len(tbody[1][1][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][0])) self.assertEqual('bar', str(tbody[1][1][0][0])) def test_desctable_for_nodes_and_edges(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = ".. seqdiag::\n :desctable:\n\n" + \ " { A -> B [description = \"foo\"]; " + \ " C -> D [description = \"bar\"]; " + \ " C [label = \"label_C\", description = foo]; " + \ " D [label = \"label_D\"]; }" doctree = publish_doctree(text) self.assertEqual(3, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) self.assertEqual(nodes.table, type(doctree[2])) # tgroup self.assertEqual(4, len(doctree[2][0])) self.assertEqual(nodes.colspec, type(doctree[2][0][0])) self.assertEqual(nodes.colspec, type(doctree[2][0][1])) self.assertEqual(nodes.thead, type(doctree[2][0][2])) self.assertEqual(nodes.tbody, type(doctree[2][0][3])) # colspec self.assertEqual(25, doctree[2][0][0]['colwidth']) self.assertEqual(50, doctree[2][0][1]['colwidth']) # thead thead = doctree[2][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[2][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('A -> B', tbody[0][0][0][0]) self.assertEqual(1, len(tbody[0][1][0])) self.assertEqual(nodes.Text, type(tbody[0][1][0][0])) self.assertEqual('foo', str(tbody[0][1][0][0])) self.assertEqual('label_C -> label_D', tbody[1][0][0][0]) self.assertEqual(1, len(tbody[1][1][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][0])) self.assertEqual('bar', str(tbody[1][1][0][0])) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.0/src/seqdiag/tests/test_generate_diagram.py��������������������������������������������0000644�0001750�0001750�00000004744�12223736264�024626� 0����������������������������������������������������������������������������������������������������ustar �katsuwo�������������������������katsuwo�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- import os import sys import re import tempfile import seqdiag.command from blockdiag.tests.utils import stderr_wrapper def extra_case(func): filename = "VL-PGothic-Regular.ttf" testdir = os.path.dirname(__file__) pathname = "%s/truetype/%s" % (testdir, filename) if os.path.exists(pathname): func.__test__ = True else: func.__test__ = False return func @stderr_wrapper def __build_diagram(filename, format, additional_args): testdir = os.path.dirname(__file__) diagpath = "%s/diagrams/%s" % (testdir, filename) fontfile = "VL-PGothic-Regular.ttf" fontpath = "%s/truetype/%s" % (testdir, fontfile) try: tmpdir = tempfile.mkdtemp() tmpfile = tempfile.mkstemp(dir=tmpdir) os.close(tmpfile[0]) args = ['-T', format, '-o', tmpfile[1], diagpath] if additional_args: if isinstance(additional_args[0], (list, tuple)): args += additional_args[0] else: args += additional_args if os.path.exists(fontpath): args += ['-f', fontpath] seqdiag.command.main(args) if re.search('ERROR', sys.stderr.getvalue()): raise RuntimeError(sys.stderr.getvalue()) finally: for file in os.listdir(tmpdir): os.unlink(tmpdir + "/" + file) os.rmdir(tmpdir) def diagram_files(): testdir = os.path.dirname(__file__) pathname = "%s/diagrams/" % testdir skipped = ['errors', 'white.gif'] return [d for d in os.listdir(pathname) if d not in skipped] def test_generator_svg(): for testcase in generator_core('svg'): yield testcase @extra_case def test_generator_png(): for testcase in generator_core('png'): yield testcase @extra_case def test_generator_pdf(): try: import reportlab.pdfgen.canvas reportlab.pdfgen.canvas for testcase in generator_core('pdf'): yield testcase except ImportError: sys.stderr.write("Skip testing about pdf exporting.\n") pass def generator_core(_format, *args): for diagram in diagram_files(): yield __build_diagram, diagram, _format, args if re.search('separate', diagram): _args = list(args) + ['--separate'] yield __build_diagram, diagram, _format, _args if _format == 'png': _args = list(args) + ['--antialias'] yield __build_diagram, diagram, _format, _args ����������������������������seqdiag-0.9.0/src/seqdiag/tests/test_pep8.py��������������������������������������������������������0000644�0001750�0001750�00000003333�12216775473�022224� 0����������������������������������������������������������������������������������������������������ustar �katsuwo�������������������������katsuwo�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- from __future__ import print_function import os import sys import pep8 CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(CURRENT_DIR) def test_pep8(): arglist = [['statistics', True], ['show-source', True], ['repeat', True], ['paths', [BASE_DIR]]] pep8style = pep8.StyleGuide(arglist, parse_argv=False, config_file=True) options = pep8style.options if options.doctest: import doctest fail_d, done_d = doctest.testmod(report=False, verbose=options.verbose) fail_s, done_s = pep8.selftest(options) count_failed = fail_s + fail_d if not options.quiet: count_passed = done_d + done_s - count_failed print("%d passed and %d failed." % (count_passed, count_failed)) if count_failed: print("Test failed.") else: print("Test passed.") if count_failed: sys.exit(1) if options.testsuite: pep8.init_tests(pep8style) report = pep8style.check_files() if options.statistics: report.print_statistics() if options.benchmark: report.print_benchmark() if options.testsuite and not options.quiet: report.print_results() if report.total_errors: if options.count: sys.stderr.write(str(report.total_errors) + '\n') #sys.exit(1) # reporting errors (additional summary) errors = report.get_count('E') warnings = report.get_count('W') message = 'pep8: %d errors / %d warnings' % (errors, warnings) print(message) assert report.total_errors == 0, message �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.0/src/seqdiag/command.py����������������������������������������������������������������0000644�0001750�0001750�00000001553�12223736264�020560� 0����������������������������������������������������������������������������������������������������ustar �katsuwo�������������������������katsuwo�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import seqdiag import seqdiag.builder import seqdiag.drawer import seqdiag.parser from blockdiag.utils.bootstrap import Application class SeqdiagApp(Application): module = seqdiag def main(args=sys.argv[1:]): return SeqdiagApp().run(args) �����������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.0/src/README.txt������������������������������������������������������������������������0000644�0001750�0001750�00000013336�12223771551�016651� 0����������������������������������������������������������������������������������������������������ustar �katsuwo�������������������������katsuwo�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������`seqdiag` generate sequence-diagram image file from spec-text file. Features ======== * Generate sequence-diagram from dot like text (basic feature). * Multilingualization for node-label (utf-8 only). You can get some examples and generated images on `blockdiag.com `_ . Setup ===== by easy_install ---------------- Make environment:: $ easy_install seqdiag by buildout ------------ Make environment:: $ hg clone http://bitbucket.org/tk0miya/seqdiag $ cd seqdiag $ python bootstrap.py $ bin/buildout Copy and modify ini file. example:: $ cp /blockdiag/examples/simple.diag . $ vi simple.diag Please refer to `spec-text setting sample`_ section for the format of the `simpla.diag` configuration file. spec-text setting sample ======================== Few examples are available. You can get more examples at `blockdiag.com `_ . simple.diag ------------ simple.diag is simply define nodes and transitions by dot-like text format:: diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } Usage ===== Execute seqdiag command:: $ seqdiag simple.diag $ ls simple.png simple.png Requirements ============ * Python 2.6, 2.7, 3.2, 3.3 * Pillow 2.2.1 * funcparserlib 0.3.6 * setuptools License ======= Apache License 2.0 History ======= 0.9.0 (2013-10-05) ------------------ * Support python 3.2 and 3.3 (thanks to @masayuko) * Drop supports for python 2.4 and 2.5 * Replace dependency: PIL -> Pillow 0.8.2 (2013-02-09) ------------------ * Fix bugs 0.8.1 (2012-11-12) ------------------ * Add altblock feature (experimental) * Fix bugs 0.8.0 (2012-10-22) ------------------ * Optimize algorithm for rendering shadow * Add options to docutils directive * Fix bugs 0.7.5 (2012-09-29) ------------------ * Fix bugs 0.7.4 (2012-09-20) ------------------ * Support blockdiag-1.1.7 interface * Fix bugs 0.7.3 (2012-03-16) ------------------ * Allow to insert separators in subedge-group * Fix bugs 0.7.2 (2011-12-12) ------------------ * Fix bugs 0.7.1 (2011-11-30) ------------------ * Fix bugs 0.7.0 (2011-11-19) ------------------ * Add fontfamily attribute for switching fontface * Fix bugs 0.6.3 (2011-11-06) ------------------ * Add docutils extention * Fix bugs 0.6.2 (2011-11-01) ------------------ * Add class feature (experimental) 0.6.1 (2011-11-01) ------------------ * Follow blockdiag-0.9.7 interface 0.6.0 (2011-10-28) ------------------ * Add edge attributes: note, rightnote, leftnote, notecolor * Add diagram atteribute: default_note_color 0.5.2 (2011-10-27) ------------------ * Implement auto edge height adjusting * Fix bugs 0.5.1 (2011-10-24) ------------------ * Fix bugs 0.5.0 (2011-10-21) ------------------ * Add diagram attributes: activation, autonumber * Add edge attribute: failed * Add separator syntax 0.4.3 (2011-10-19) ------------------ * Follow blockdiag-0.9.5 interface 0.4.2 (2011-10-11) ------------------ * Fix bugs 0.4.1 (2011-09-30) ------------------ * Add diagram attribute: default_text_color * Add node attribte: textcolor * Fix bugs 0.4.0 (2011-09-26) ------------------ * Add diagram attributes: default_node_color, default_group_color and default_line_color 0.3.8 (2011-08-02) ------------------ * Allow dot characters in node_id * Fix bugs 0.3.7 (2011-07-05) ------------------ * Fix bugs 0.3.6 (2011-07-03) ------------------ * Support input from stdin 0.3.5 (2011-06-02) ------------------ * Fix bugs 0.3.4 (2011-05-18) ------------------ * Fix bugs 0.3.3 (2011-05-16) ------------------ * Add --version option * Add sphinxhelper module 0.3.2 (2011-05-14) ------------------ * Render group label * Support blockdiag 0.8.1 core interface 0.3.1 (2011-04-22) ------------------ * Render group label * Fix sphinxcontrib_seqdiag does not work with seqdiag 0.3.0 0.3.0 (2011-04-22) ------------------ * Add group syntax 0.2.7 (2011-04-15) ------------------ * Adjust start coordinates of edges 0.2.6 (2011-04-14) ------------------ * Fix bugs * Allow unquoted utf8 characters 0.2.5 (2011-03-26) ------------------ * Fix seqdiag could not run under blockdiag 0.7.6 0.2.4 (2011-03-20) ------------------ * Fix bugs 0.2.3 (2011-03-09) ------------------ * Fix bugs 0.2.2 (2011-03-07) ------------------ * Fix could not run under python 2.4 * Support edge colors 0.2.1 (2011-02-28) ------------------ * Add default_shape attribute to diagram 0.2.0 (2011-02-27) ------------------ * Add metrix parameters for edge label: edge_height, edge_length * Fix bugs 0.1.7 (2011-01-21) ------------------ * Fix TeX exporting in Sphinx extension 0.1.6 (2011-01-15) ------------------ * Support blockdiag-0.6.3 * Fix bugs 0.1.5 (2011-01-15) ------------------ * Draw activity on lifelines * Support both direction edge with '=>' operator 0.1.4 (2011-01-13) ------------------ * Change synxtax around edges 0.1.3 (2011-01-12) ------------------ * Support diagonal edge * Fix bugs 0.1.2 (2011-01-11) ------------------ * Support nested edges * Add edge attributes; return, dir * Add sphinx extention module(sphinxcontrib_seqdiag) * Fix bugs 0.1.1 (2011-01-11) ------------------ * Fix bugs about layouting 0.1.0 (2011-01-08) ------------------ * first release ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.0/setup.cfg�����������������������������������������������������������������������������0000644�0001750�0001750�00000000161�12224000732�016160� 0����������������������������������������������������������������������������������������������������ustar �katsuwo�������������������������katsuwo�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [build] build-base = _build [sdist] formats = gztar ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.0/MANIFEST.in���������������������������������������������������������������������������0000644�0001750�0001750�00000000254�11642765263�016124� 0����������������������������������������������������������������������������������������������������ustar �katsuwo�������������������������katsuwo�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������include buildout.cfg include bootstrap.py include MANIFEST.in include LICENSE include seqdiag.1 recursive-include examples *.diag recursive-include src *.py *.txt ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.0/LICENSE�������������������������������������������������������������������������������0000644�0001750�0001750�00000026136�11561164153�015371� 0����������������������������������������������������������������������������������������������������ustar �katsuwo�������������������������katsuwo�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������