[med-svn] [seqan2] 01/01: New upstream version 2.3.2+dfsg2

Michael Crusoe misterc-guest at moszumanska.debian.org
Fri Oct 13 12:04:37 UTC 2017


This is an automated email from the git hooks/post-receive script.

misterc-guest pushed a commit to annotated tag upstream/2.3.2+dfsg2
in repository seqan2.

commit 5f349621ab5eb6643ed8a5f373b865daf0f65b6b
Author: Michael R. Crusoe <michael.crusoe at gmail.com>
Date:   Fri Oct 13 04:38:14 2017 -0700

    New upstream version 2.3.2+dfsg2
---
 util/py_lib/CMakeLists.txt                      |  34 ++
 util/py_lib/seqan/LICENSE                       |  26 ++
 util/py_lib/seqan/__init__.py                   |   0
 util/py_lib/seqan/app_tests.py                  | 458 ++++++++++++++++++++
 util/py_lib/seqan/auto_build.py                 | 532 ++++++++++++++++++++++++
 util/py_lib/seqan/fixgcov/README                |  22 +
 util/py_lib/seqan/fixgcov/__init__.py           |  10 +
 util/py_lib/seqan/fixgcov/app.py                | 291 +++++++++++++
 util/py_lib/seqan/paths.py                      |  65 +++
 util/py_lib/seqan/pyclangcheck/__init__.py      |  10 +
 util/py_lib/seqan/pyclangcheck/app.py           | 322 ++++++++++++++
 util/py_lib/seqan/pyclangcheck/rules.py         | 201 +++++++++
 util/py_lib/seqan/pyclangcheck/simple_checks.py | 117 ++++++
 util/py_lib/seqan/pyclangcheck/suppressions.py  |   1 +
 util/py_lib/seqan/pyclangcheck/violations.py    |  91 ++++
 util/py_lib/seqan/seqan.css                     |   7 +
 util/py_lib/seqan/seqan.html                    | 148 +++++++
 util/py_lib/seqan/skel.py                       | 467 +++++++++++++++++++++
 18 files changed, 2802 insertions(+)

diff --git a/util/py_lib/CMakeLists.txt b/util/py_lib/CMakeLists.txt
new file mode 100644
index 0000000..ef4b578
--- /dev/null
+++ b/util/py_lib/CMakeLists.txt
@@ -0,0 +1,34 @@
+# ===========================================================================
+#                  SeqAn - The Library for Sequence Analysis
+# ===========================================================================
+# File: /util/py_lib/CMakeLists.txt
+#
+# CMakeLists.txt file for Python stuff.
+# ===========================================================================
+# Kicks off tests using Python nosetests.
+# ===========================================================================
+
+# Look for Python and stop if it could not be found.
+find_package (PythonInterp)
+
+if (NOT PYTHONINTERP_FOUND)
+  message (STATUS "  Python not found, cannot test py_lib.")
+  return ()
+endif (NOT PYTHONINTERP_FOUND)
+
+# Look for nosetests and stop if it cannot be found
+execute_process(COMMAND ${PYTHON_EXECUTABLE} -m "nose"
+                RESULT_VARIABLE PYTHON_NOSETESTS_NOT_FOUND
+                OUTPUT_VARIABLE _IGNORED
+                ERROR_VARIABLE _IGNORED)
+
+if (PYTHON_NOSETESTS_NOT_FOUND)
+  message (STATUS "  Python nosetests ('import nose' failed), cannot add tests for seqan.dox")
+  return ()
+endif (PYTHON_NOSETESTS_NOT_FOUND)
+
+# Adding test for dox.
+message (STATUS "  adding nosetests for seqan.dox")
+add_test (NAME test_py_lib_dox
+          COMMAND nosetests
+          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/seqan/dox)
diff --git a/util/py_lib/seqan/LICENSE b/util/py_lib/seqan/LICENSE
new file mode 100644
index 0000000..61f9fdf
--- /dev/null
+++ b/util/py_lib/seqan/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the <organization> nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/util/py_lib/seqan/__init__.py b/util/py_lib/seqan/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/util/py_lib/seqan/app_tests.py b/util/py_lib/seqan/app_tests.py
new file mode 100644
index 0000000..2cc71bc
--- /dev/null
+++ b/util/py_lib/seqan/app_tests.py
@@ -0,0 +1,458 @@
+#!/usr/bin/env python2
+"""Helper code for app tests.
+
+This module contains helper functions and classes for making app tests easy.
+The advantage of using Python for this is easier portability instead of relying
+on Unix tools such as bash and diff which are harder to install on Windows than
+Python.
+
+App tests are performed by executing the programs on test data and comparing
+their output to previously generated "golden" output files.
+
+Classes/Functions:
+
+  class TestConf -- stores configuration of a test.
+  class TestPathHelper -- helps with constructing paths.
+  function runTest -- runs a test configured by a TestConf object.
+  function autolocateBinary -- locates a binary, possibly in an intermediary
+                               directory.
+"""
+
+from __future__ import with_statement
+
+__author__ = 'Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>'
+
+import difflib
+import hashlib
+import logging
+import optparse
+import os
+import os.path
+import re
+import subprocess
+import shutil
+import sys
+import tempfile
+import gzip
+
+def md5ForFile(f, block_size=2**20):
+    """Compute MD5 of a file.
+
+    Taken from http://stackoverflow.com/a/1131255/84349.
+    """
+    md5 = hashlib.md5()
+    while True:
+        data = f.read(block_size)
+        if not data:
+            break
+        md5.update(data)
+    return md5.hexdigest()
+
+
+# Valgrind flags, taken from CMake output, ideally given to test script by CMake?
+SUPPRESSIONS = '--suppressions=' + os.path.join(os.path.dirname(__file__), '..', '..', '..', 'misc', 'seqan.supp')
+VALGRIND_FLAGS = [SUPPRESSIONS] + '--error-exitcode=1 -q --tool=memcheck --leak-check=yes --show-reachable=yes --workaround-gcc296-bugs=yes --num-callers=50 --'.split()
+VALGRIND_PATH = '/usr/bin/valgrind'
+
+class BadResultException(Exception):
+    pass
+
+
+class TestConf(object):
+    """Configuration for one tests.
+
+    A test configuration consists of the parameters to give to the
+    program and the expected result.
+
+    Attrs:
+      program -- string, path to binary to execute.
+      args -- list of strings with arguments to the program.
+      to_diff -- optional list of pairs with (output-file, expected-file) paths
+                 diff, the contents of output-file should be equal to the
+                 contents of expected-file.
+      name -- optional string, name of the test.
+      redir_stdout -- optional string that gives the path to redirect stdout to
+                      if the variable is not None.
+      redir_stderr -- optional string that gives the path to redirect stderr to
+                      if the variable is not None.
+      check_callback -- callable throwing an exception on erorrs.
+    """
+
+    def __init__(self, program, args, to_diff=[], name=None,
+                 redir_stdout=None, redir_stderr=None,
+                 check_callback=None):
+        """Constructor, args correspond to attrs."""
+        self.program = program
+        self.args = args
+        self.to_diff = to_diff
+        self.name = name
+        self.redir_stdout = redir_stdout
+        self.redir_stderr = redir_stderr
+        if not hasattr(TestConf, 'valgrind'):
+            self.valgrind = False
+        else:
+            self.valgrind = TestConf.valgrind
+        self.check_callback = check_callback
+
+    def __str__(self):
+        fmt = 'TestConf(%s, %s, %s, %s, %s, %s)'
+        return fmt % (repr(self.program), self.args, self.to_diff, self.name,
+                      self.redir_stdout, self.redir_stderr)
+
+    def commandLineArgs(self):
+        """Returns the command line."""
+        args = [x for x in self.args if x != '']
+        args = [self.program] + args
+        if self.valgrind:
+            args = [VALGRIND_PATH] + VALGRIND_FLAGS + args
+        return args
+
+
+class TestPathHelper(object):
+    """Helper class for paths.
+
+    TestPathHelper objects are configured with the appropriate paths.  The
+    provide functions to construct when executing tests.
+    """
+
+    def __init__(self, source_base_path, binary_base_path,
+                 tests_dir):
+        self.temp_dir = None
+        self.source_base_path = source_base_path
+        self.binary_base_path = binary_base_path
+        self.tests_dir = tests_dir
+        self.created_paths = []
+
+    def inFile(self, path):
+        """Convert the path of a test file.
+
+        The given path, relative to the test directory, will be transformed into an
+        absolute path to the file.
+
+        Args:
+          path -- relative path to a file in the test directory.
+
+        Returns:
+          Absolute to the file.
+        """
+        result = os.path.join(self.source_base_path, self.tests_dir, path)
+        logging.debug('inFile(%s) = %s', path, result)
+        return result
+
+    def outFile(self, path, subdir=None):
+        """Convert the path of an output file.
+
+        The given path will be converted to a path to a temporary file.  The path
+        to this file will be created.
+
+        If subdir is set then a subdirectory with this name will be created and
+        the output will be relative to subdir.
+        """
+        if not self.temp_dir:
+            self.temp_dir = tempfile.mkdtemp()
+            if not os.path.isdir(self.temp_dir):
+                self.created_paths.append(self.temp_dir)
+                os.makedirs(self.temp_dir)
+        target_dir = self.temp_dir
+        if subdir:
+            target_dir = os.path.join(self.temp_dir, subdir)
+            if not os.path.isdir(target_dir):
+                self.created_paths.append(target_dir)
+                os.makedirs(target_dir)
+        logging.debug('outFile(%s, %s) = %s', path, subdir, self.temp_dir)
+        res = os.path.join(target_dir, path)
+        self.created_paths.append(res)
+        return res
+
+    def deleteTempDir(self):
+        """Remove the temporary directory created earlier and all files below."""
+        print >>sys.stderr, 'DELETING TEMP DIR', self.temp_dir
+        if self.temp_dir:
+            shutil.rmtree(self.temp_dir)
+
+
+def autolocateBinary(base_path, relative_path, binary_name):
+  """Autolocates a binary, possibly in an intermediary path.
+
+  When building applications with CMake, they do not always have the same
+  relative path from the binary build directory.  For Unix Makefiles, the path
+  could be 'apps/tree_recon' whereas for Visual Studio, it could be
+  'apps/Release/tree_recon'.
+
+  Also, it searches for the binary name in "${base_path}/bin".
+
+  This function tries to automatically guess the name of the file and return
+  the first one it finds.
+  """
+  # Names of intermediary directories and possible file extensions.
+  intermediary_dir_names = ['', 'Debug', 'Release']
+  extensions = ['', '.exe']
+  paths = [os.path.join(base_path, 'bin', binary_name),
+           os.path.join(base_path, 'bin', 'Debug', binary_name),
+           os.path.join(base_path, 'bin', 'Release', binary_name),
+           os.path.join(base_path, 'bin', binary_name + '.exe'),
+           os.path.join(base_path, 'bin', 'Debug', binary_name + '.exe'),
+           os.path.join(base_path, 'bin', 'Release', binary_name + '.exe')]
+  # Try all possible paths.
+  for dir_name in intermediary_dir_names:
+    for ext in extensions:
+      # With CMAKE_BINARY_DIR not set to "bin".
+      res_list = [base_path, relative_path, dir_name, binary_name + ext]
+      filtered_list = [x for x in res_list if x]  # Filter out empty strings.
+      paths.append(os.path.join(*filtered_list))
+      if dir_name:
+        paths.append('/'.join([base_path] + relative_path.split('/')[:-1] +
+                              [dir_name] + relative_path.split('/')[-1:] +
+                              [binary_name]))
+  for path in paths:
+    logging.debug('Trying path %s', path)
+    if os.path.isfile(path):
+      logging.debug('  Found binary %s', path)
+      return path
+  # Fall back ot Unix default.
+  return os.path.join(base_path, relative_path, binary_name)
+
+
+def runTest(test_conf):
+    """Run the test configured in test_conf.
+
+    Args:
+      test_conf -- TestConf object to run test for.
+
+    Returns:
+      True on success, False on any errors.
+
+    Side Effects:
+      Errors are printed to stderr.
+    """
+    # Execute the program.
+    logging.debug('runTest(%s)', test_conf)
+    logging.debug('Executing "%s"', ' '.join(test_conf.commandLineArgs()))
+    stdout_file = subprocess.PIPE
+    if test_conf.redir_stdout:
+        logging.debug('  Redirecting stdout to "%s".' % test_conf.redir_stdout)
+        stdout_file = open(test_conf.redir_stdout, 'w+')
+    stderr_file = subprocess.PIPE
+    if test_conf.redir_stderr:
+        logging.debug('  Redirecting stderr to "%s".' % test_conf.redir_stderr)
+        stderr_file = open(test_conf.redir_stderr, 'w+')
+    try:
+        process = subprocess.Popen(test_conf.commandLineArgs(), stdout=stdout_file,
+                                   stderr=stderr_file)
+        retcode = process.wait()
+        logging.debug('  return code is %d', retcode)
+        if retcode != 0:
+            fmt = 'Return code of command "%s" was %d.'
+            print >>sys.stderr, '--- stdout begin --'
+            print >>sys.stderr, fmt % (' '.join(test_conf.commandLineArgs()), retcode)
+            print >>sys.stderr, stdout_file.read()
+            print >>sys.stderr, '--- stdout end --'
+            stdout_file.close()
+            if process.stderr:
+                stderr_contents = process.stderr.read()
+            else:
+                stderr_contents = ''
+            print >>sys.stderr, '-- stderr begin --'
+            print >>sys.stderr, stderr_contents
+            print >>sys.stderr, '-- stderr end --'
+            return False
+    except Exception, e:
+        # Print traceback.
+        import traceback
+        exc_type, exc_value, exc_traceback = sys.exc_info()
+        traceback.print_exception(exc_type, exc_value, exc_traceback)
+        fmt = 'ERROR (when executing "%s"): %s'
+        if stdout_file is not subprocess.PIPE:
+            stdout_file.close()
+        print >>sys.stderr, fmt % (' '.join(test_conf.commandLineArgs()), e)
+        return False
+    # Handle error of program, indicated by return code != 0.
+    if retcode != 0:
+        print >>sys.stderr, 'Error when executing "%s".' % ' '.join(test_conf.commandLineArgs())
+        print >>sys.stderr, 'Return code is %d' % retcode
+        if stdout_file is not subprocess.PIPE:
+            stdout_file.seek(0)
+        stdout_contents = process.stdout.read()
+        if stdout_contents:
+            print >>sys.stderr, '-- stdout begin --'
+            print >>sys.stderr, stdout_contents
+            print >>sys.stderr, '-- stdout end --'
+        else:
+            print >>sys.stderr, '-- stdout is empty --'
+        stderr_contents = process.stderr.read()
+        if stderr_contents:
+            print >>sys.stderr, '-- stderr begin --'
+            print >>sys.stderr, stderr_contents
+            print >>sys.stderr, '-- stderr end --'
+        else:
+            print >>sys.stderr, '-- stderr is empty --'
+    # Close standard out file if necessary.
+    if stdout_file is not subprocess.PIPE:
+        stdout_file.close()
+    # Compare results with expected results, if the expected and actual result
+    # are not equal then print diffs.
+    result = True
+    for tuple_ in test_conf.to_diff:
+        expected_path, result_path = tuple_[:2]
+        binary = False
+        gunzip = False
+        transforms = [NormalizeLineEndingsTransform()]
+        if len(tuple_) >= 3:
+            if tuple_[2] == 'md5':
+                binary = True
+            elif tuple_[2] == 'gunzip':
+                binary = True
+                gunzip = True
+            else:
+                transforms += tuple_[2]
+        try:
+            if gunzip:
+                f = gzip.open(expected_path, 'rb')
+                expected_md5 = md5ForFile(f)
+                f.close()
+                f = gzip.open(result_path, 'rb')
+                result_md5 = md5ForFile(f)
+                f.close()
+                if expected_md5 == result_md5:
+                    continue
+                else:
+                    tpl = (expected_path, expected_md5, result_md5, result_path)
+                    print >>sys.stderr, 'md5(gunzip(%s)) == %s != %s == md5(gunzip(%s))' % tpl
+                    result = False
+            if binary:
+                with open(expected_path, 'rb') as f:
+                    expected_md5 = md5ForFile(f)
+                with open(result_path, 'rb') as f:
+                    result_md5 = md5ForFile(f)
+                if expected_md5 == result_md5:
+                    continue
+                else:
+                    tpl = (expected_path, expected_md5, result_md5, result_path)
+                    print >>sys.stderr, 'md5(%s) == %s != %s == md5(%s)' % tpl
+                    result = False
+            else:
+                with open(expected_path, 'rb') as f:
+                    expected_str = f.read()
+                for t in transforms:
+                    expected_str = t.apply(expected_str, True)
+                with open(result_path, 'rb') as f:
+                    result_str = f.read()
+                for t in transforms:
+                    result_str = t.apply(result_str, False)
+                if expected_str == result_str:
+                    continue
+                fmt = 'Comparing %s against %s'
+                print >>sys.stderr, fmt % (expected_path, result_path)
+                diff = difflib.unified_diff(expected_str.splitlines(),
+                                            result_str.splitlines())
+                for line in diff:
+                    print >>sys.stderr, line
+                result = False
+        except Exception, e:
+            fmt = 'Error when trying to compare %s to %s: %s ' + str(type(e))
+            print >>sys.stderr, fmt % (expected_path, result_path, e)
+            result = False
+    # Call check callable.
+    if test_conf.check_callback:
+        try:
+            test_conf.check_callback()
+        except BadResultException, e:
+            print >>sys.stderr, 'Bad result: ' + str(e)
+            result = False
+        except Exception, e:
+            print >>sys.stderr, 'Error in checker: ' + str(type(e)) + ' ' + str(e)
+            result = False
+    return result
+
+
+class ReplaceTransform(object):
+    """Transformation on left and/or right files to diff."""
+
+    def __init__(self, needle, replacement, left=True, right=True):
+        self.needle = needle
+        self.replacement = replacement
+        self.left = left
+        self.right = right
+
+    def apply(self, text, is_left):
+        if (is_left and not self.left) or (not is_left and not self.right):
+            return text  # Skip if no transform is to be applied.
+        return text.replace(self.needle, self.replacement)
+
+
+class NormalizeLineEndingsTransform(object):
+    """Normalizes line endings to '\n'."""
+
+    def __init__(self, left=True, right=True):
+        self.left = left
+        self.right = right
+
+    def apply(self, text, is_left):
+        if (is_left and not self.left) or (not is_left and not self.right):
+            return text  # Skip if no transform is to be applied.
+        return text.replace('\r\n', '\n')
+
+
+class NormalizeScientificExponentsTransform(object):
+    """Transformation that normalized scientific notation exponents.
+
+    On Windows, scientific numbers are printed with an exponent padded to
+    a width of three with zeros, e.g. 1e003 instead of 1e03 as on Unix.
+
+    This transform normalizes to Unix or Windows.
+    """
+
+    def __init__(self, normalize_to_unix=True):
+        self.normalize_to_unix = normalize_to_unix
+
+    def apply(self, text, is_left):
+        """Apply the transform."""
+        if self.normalize_to_unix:
+            return re.sub(r'([-+]?(?:[0-9]*\.)?[0-9]+[eE][\-+]?)0([0-9]{2})', r'\1\2', text)
+        else:
+            return re.sub(r'([-+]?(?:[0-9]*\.)?[0-9]+[eE][\-+]?)([0-9]{2})', r'\10\2', text)
+
+
+class RegexpReplaceTransform(object):
+    """Transformation that applies regular expression replacement."""
+
+    def __init__(self, needle, replacement, left=True, right=True):
+        self.needle = needle
+        self.replacement = replacement
+        self.left = left
+        self.right = right
+
+    def apply(self, text, is_left):
+        """Apply the transform."""
+        if (is_left and not self.left) or (not is_left and not self.right):
+            return text  # Skip if no transform is to be applied.
+        return re.sub(self.needle, self.replacement, text)
+
+
+class UniqueTransform(object):
+    """Unique sort transformation on left and/or right files to diff."""
+
+    def __init__(self, left=True, right=True):
+        self.left = left
+        self.right = right
+
+    def apply(self, text, is_left):
+        if (is_left and not self.left) or (not is_left and not self.right):
+            return text  # Skip if no transform is to be applied.
+        return ''.join(sorted(set(text.splitlines(True))))
+
+
+def main(main_func, **kwargs):
+    """Run main_func with the first and second positional parameter."""
+    parser = optparse.OptionParser("usage: run_tests [options] SOURCE_ROOT_PATH BINARY_ROOT_PATH")
+    parser.add_option('-v', '--verbose', dest='verbose', action='store_true')
+    parser.add_option('--valgrind', dest='valgrind', action='store_true')
+    (options, args) = parser.parse_args()
+    if len(args) != 2:
+        parser.error('Incorrect number of arguments!')
+        return 2
+    if options.verbose:
+        logging.root.setLevel(logging.DEBUG)
+    if options.valgrind:
+        TestConf.valgrind = True
+    return main_func(args[0], args[1], **kwargs)
diff --git a/util/py_lib/seqan/auto_build.py b/util/py_lib/seqan/auto_build.py
new file mode 100755
index 0000000..9ae7e27
--- /dev/null
+++ b/util/py_lib/seqan/auto_build.py
@@ -0,0 +1,532 @@
+#!/usr/bin/env python2
+"""
+Automatic building of SeqAn apps and releases.
+"""
+
+from __future__ import print_function
+
+import subprocess
+import optparse
+import os.path
+import re
+import sys
+import shutil
+import tempfile
+
+# The git command to use.
+GIT_BINARY='git'
+# The CMake command to use.
+CMAKE_BINARY='cmake'
+
+# The default repository URL.
+REPOSITORY_URL='https://github.com/seqan/seqan.git'
+# The path to the package repository.
+DEFAULT_PACKAGE_DB='.'
+
+# Regular expression to use for tag names.
+TAG_RE=r'.*-v\d+\.\d+\.\d(-\w+)?'
+
+class MinisculeGitWrapper(object):
+    """Minimal git wrapper."""
+
+    def lsRemote(self, url):
+        """Execute 'git ls-remote ${url} --tags'."""
+        # Execute ls-remote command.
+        print('Executing "%s %s %s"' % (GIT_BINARY, 'ls-remote --tags', url), file=sys.stderr)
+        popen = subprocess.Popen([GIT_BINARY, 'ls-remote', '--tags', url],
+                                 stdout=subprocess.PIPE)
+        out_data, err_data = popen.communicate()
+        print('  => %d' % popen.returncode, file=sys.stderr)
+        if popen.returncode != 0:
+            print('ERROR during git call.', file=sys.stderr)
+            return 1
+        # Parse out revisions and tags names.
+        lines = out_data.splitlines()
+        revs_tags = [(line.split()[0], line.split()[-1]) for line in lines]
+        res = []
+        for rev, tag in revs_tags:
+            if '^{}' in tag:
+                continue  # Skip with ^{} in tag name
+            tag2 = tag[10:]
+            res.append((rev, tag2))
+        return res
+
+    def checkout(self, path, treeish):
+        """Execute "git checkout" in the checkout at path."""
+        # Executing git checkout.
+        args = [GIT_BINARY, 'checkout', treeish]
+        print('Executing "%s" in "%s"' % (' '.join(args), path), file=sys.stderr)
+        popen = subprocess.Popen(args, cwd=path)
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during git call.', file=sys.stderr)
+        # Executing force resetting to current revision.
+        args = [GIT_BINARY, 'rm', '--cached', '.']
+        print('Executing "%s" in "%s"' % (' '.join(args), path), file=sys.stderr)
+        popen = subprocess.Popen(args, cwd=path)
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during git call.', file=sys.stderr)
+        args = [GIT_BINARY, 'reset', '--hard']
+        print('Executing "%s" in "%s"' % (' '.join(args), path), file=sys.stderr)
+        popen = subprocess.Popen(args, cwd=path)
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during git call.', file=sys.stderr)
+        return popen.returncode
+
+    def archive(self, path, treeish, output, prefix):
+        """Execute git archive."""
+        args = [GIT_BINARY, 'archive', '--prefix=%s/' % prefix, '--output=%s' % output, treeish]
+        print('Executing "%s" in "%s"' % (' '.join(args), path), file=sys.stderr)
+        popen = subprocess.Popen(args, cwd=path)
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during git call.', file=sys.stderr)
+        return popen.returncode
+
+    def clone(self, url, tag, dest_dir):
+        """Execute 'git clone ${url} ${dest_dir}' and then get specific tag."""
+        # Clone repository
+        args = [GIT_BINARY, 'clone', url, dest_dir]
+        print('Executing "%s"' % ' '.join(args), file=sys.stderr)
+        popen = subprocess.Popen(args)
+        popen.wait()
+        print('  => %d' % popen.returncode, file=sys.stderr)
+        if popen.returncode != 0:
+            return popen.returncode
+        return self.checkout(dest_dir, tag)
+
+
+class Package(object):
+    """Represent a package with a given name, version, OS and architeture."""
+
+    def __init__(self, name, version, os, word_size, pkg_format):
+        self.name = name
+        self.version = version
+        self.os = os
+        self.word_size = word_size
+        SYS_NAMES = {'Windows': {'32': 'win32-i686', '64': 'win64-x86_64'},
+                     'Linux': {'32': 'Linux-i686', '64': 'Linux-x86_64'},
+                     'Mac': {'32': 'Darwin-i686', '64': 'Darwin-x86_64'}}
+        self.system_name = SYS_NAMES[os][word_size]
+        self.pkg_format = pkg_format
+
+    def fileName(self):
+        if self.name == 'seqan-library':
+            return '%s-%s.%s' % (self.name, self.version, self.pkg_format)
+        else:
+            return '%s-%s-%s.%s' % (self.name, self.version, self.system_name,
+                                    self.pkg_format)
+
+
+class BuildStep(object):
+    """Management of one build step."""
+
+    def __init__(self, path, treeish, name, version, os, word_size, pkg_formats,
+                 repository_url, make_args, options, tmp_dir=None):
+        self.base_path = path
+        self.treeish = treeish
+        self.name = name
+        self.version = version.split('-', 1)[0]
+        print ( 'Version: %s Self.Version: %s' % (version, self.version), file=sys.stdout)
+        self.major_version = int(self.version.split('.')[0])
+        print ( 'Major_Version: %s' % self.major_version, file=sys.stdout)
+        self.minor_version = int(self.version.split('.')[1])
+        print ( 'Minor_Version: %s' % self.minor_version, file=sys.stdout)
+        self.patch_version = 0
+        if len(self.version.split('.')) > 2:
+            self.patch_version = int(self.version.split('.')[2])
+        self.version = '%d.%d.%d' % (self.major_version, self.minor_version, self.patch_version)
+        print ( 'Self_Version: %s' % self.version, file=sys.stdout)
+        self.os = os
+        self.word_size = word_size
+        self.pkg_formats = pkg_formats
+        if name == 'seqan':
+            self.packages = [Package(name + suffix, self.version, os, word_size, f)
+                             for f in pkg_formats for suffix in ['-apps', '-library']]
+        else:
+            self.packages = [Package(name, self.version, os, word_size, f)
+                             for f in pkg_formats]
+        self.repository_url = repository_url
+        self.make_args = make_args
+        self.options = options
+        # If set then this is used instead of a random name in TMPDIR.
+        self.tmp_dir = tmp_dir
+
+    def buildNeeded(self):
+        """Returns whether one of the package files is missing."""
+        for p in self.packages:
+            package_path = os.path.join(self.base_path, p.name, p.fileName())
+            if 'x86' in package_path and 'x86_64' not in package_path:  # fix processor name
+                package_path = package_path.replace('x86', 'x86_64')
+            if 'win32' in package_path or 'win64' in package_path:  # fix OS name
+                package_path = package_path.replace('win32', 'Windows').replace('win64', 'Windows')
+            if 'Darwin' in package_path:  # fix OS name
+                package_path = package_path.replace('Darwin', 'Mac')
+            if not os.path.exists(package_path):
+                if self.options.verbosity >= 1:
+                    print('File %s does not exist yet.' % package_path, file=sys.stderr)
+                return True
+            elif self.options.verbosity >= 1:
+                print('File %s exists.' % package_path, file=sys.stderr)
+        return False
+
+    def copyArchives(self, build_dir):
+        """Copy built packages to base_path directory."""
+        for p in self.packages:
+            from_ = os.path.join(build_dir, p.fileName())
+            if os.path.exists(from_):
+                to = os.path.join(self.base_path, p.name, os.path.basename(from_))
+                if not os.path.exists(os.path.dirname(to)):  # Create directory if necessary.
+                    os.makedirs(os.path.dirname(to))
+                print("Copying %s => %s" % (from_, to), file=sys.stderr)
+                if 'x86' in to and 'x86_64' not in to:  # fix processor name
+                    to = to.replace('x86', 'x86_64')
+                if 'win32' in to or 'win64' in to:  # fix OS name
+                    to = to.replace('win32', 'Windows').replace('win64', 'Windows')
+                if 'Darwin' in to:  # fix OS name
+                    to = to.replace('Darwin', 'Mac')
+                shutil.copyfile(from_, to)
+            else:
+                print('%s does not exist (not fatal)' % from_, file=sys.stderr)
+
+    def buildSeqAnRelease(self, checkout_dir, build_dir):
+        """Build SeqAn release: Apps and library build."""
+        # Build seqan-apps.
+        #
+        # Create build directory.
+        if not os.path.exists(build_dir):
+            print('Creating build directory %s' % (build_dir,), file=sys.stderr)
+            os.mkdir(build_dir)
+        # Execute CMake.
+        cmake_args = [CMAKE_BINARY, checkout_dir,
+                      '-DSEQAN_BUILD_SYSTEM=SEQAN_RELEASE_APPS']
+        # Use appropriate CMake flags for OS and processor.
+        # Use appropriate CMake flags for OS and processor.
+        if self.word_size == '32':
+            cmake_args.append('-DSEQAN_SYSTEM_PROCESSOR=i686')
+            if self.os != 'Windows':
+                cmake_args.append('-DCMAKE_CXX_FLAGS=-m32')
+            else:
+                cmake_args += ['-G', 'Visual Studio 10']
+        else:  # self.word_size == '64'
+            cmake_args.append('-DSEQAN_SYSTEM_PROCESSOR=x86_64')
+            if self.os == 'Windows':
+                cmake_args += ['-G', 'Visual Studio 10 Win64']
+        print('Executing CMake: "%s"' % (' '.join(cmake_args),), file=sys.stderr)
+        popen = subprocess.Popen(cmake_args, cwd=build_dir, env=os.environ.copy())
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during make call.', file=sys.stderr)
+            print(out_data, file=sys.stderr)
+            print(err_data, file=sys.stderr)
+            return 1
+        # Execute Make.
+        cmake_args = [CMAKE_BINARY, '--build', build_dir, '--target', 'package', '--config', 'Release', '--'] + self.make_args
+        print('Building with CMake: "%s"' % (' '.join(cmake_args),), file=sys.stderr)
+        popen = subprocess.Popen(cmake_args, cwd=build_dir, env=os.environ.copy())
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during make call.', file=sys.stderr)
+            print(out_data, file=sys.stderr)
+            print(err_data, file=sys.stderr)
+            return 1
+        # Copy over the archives.
+        self.copyArchives(build_dir)
+        # Remove build directory.
+        if not self.options.keep_build_dir:
+            print('Removing build directory %s' % build_dir, file=sys.stderr)
+            shutil.rmtree(build_dir)
+        # Build seqan-library.
+        #
+        # Create build directory.
+        if not os.path.exists(build_dir):
+            print("Creating build directory %s" % (build_dir,), file=sys.stderr)
+            os.mkdir(build_dir)
+        # Execute CMake.
+        cmake_args = [CMAKE_BINARY, checkout_dir,
+                      "-DSEQAN_BUILD_SYSTEM=SEQAN_RELEASE_LIBRARY"]
+        print('Executing CMake: "%s"' % (' '.join(cmake_args),), file=sys.stderr)
+        popen = subprocess.Popen(cmake_args, cwd=build_dir, env=os.environ.copy())
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during make call.', file=sys.stderr)
+            print(out_data, file=sys.stderr)
+            print(err_data, file=sys.stderr)
+            return 1
+        # Build Docs
+        cmake_args = [CMAKE_BINARY, '--build', build_dir, '--target', 'docs', '--'] + self.make_args
+        print('Building with CMake: "%s"' % (' '.join(cmake_args),), file=sys.stderr)
+        popen = subprocess.Popen(cmake_args, cwd=build_dir, env=os.environ.copy())
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during make dox call.', file=sys.stderr)
+            print(out_data, file=sys.stderr)
+            print(err_data, file=sys.stderr)
+        # Execute Make.
+        cmake_args = [CMAKE_BINARY, '--build', build_dir, '--target', 'package', '--'] + self.make_args
+        print('Building with CMake: "%s"' % (' '.join(cmake_args),), file=sys.stderr)
+        popen = subprocess.Popen(cmake_args, cwd=build_dir, env=os.environ.copy())
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during make call.', file=sys.stderr)
+            print(out_data, file=sys.stderr)
+            print(err_data, file=sys.stderr)
+            return 1
+        self.copyArchives(build_dir)
+        # Remove build directory.
+        if not self.options.keep_build_dir:
+            print('Removing build directory %s' % build_dir, file=sys.stderr)
+            shutil.rmtree(build_dir)
+
+    def buildApp(self, checkout_dir, build_dir):
+        """Build an application."""
+        # Create build directory.
+        print("Creating build directory %s" % (build_dir,), file=sys.stderr)
+        if not os.path.exists(build_dir):
+            os.mkdir(build_dir)
+        # Execute CMake.
+        cmake_args = [CMAKE_BINARY, checkout_dir,# '-G', 'Visual Studio 10',
+                      "-DCMAKE_BUILD_TYPE=Release",
+                      "-DSEQAN_BUILD_SYSTEM=APP:%s" % self.name,
+                      "-DSEQAN_APP_VERSION=%d.%d.%d" %
+                        (self.major_version, self.minor_version, self.patch_version)]
+        # Use appropriate CMake flags for OS and processor.
+        if self.word_size == '32':
+            cmake_args.append('-DSEQAN_SYSTEM_PROCESSOR=i686')
+            if self.os != 'Windows':
+                cmake_args.append('-DCMAKE_CXX_FLAGS=-m32')
+            else:
+                cmake_args += ['-G', 'Visual Studio 10']
+        else:  # self.word_size == '64'
+            cmake_args.append('-DSEQAN_SYSTEM_PROCESSOR=x86_64')
+            if self.os == 'Windows':
+                cmake_args += ['-G', 'Visual Studio 10 Win64']
+        print('Executing CMake: "%s"' % (' '.join(cmake_args),), file=sys.stderr)
+        #for key in sorted(os.environ.keys()):
+        #    print(key, ': ', os.environ[key], file=sys.stderr)
+        popen = subprocess.Popen(cmake_args, cwd=build_dir, env=os.environ.copy())
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during make call.', file=sys.stderr)
+            print(out_data, file=sys.stderr)
+            print(err_data, file=sys.stderr)
+            return 1
+        # Build and package project.
+        make_args = [CMAKE_BINARY, '--build', build_dir, '--target', 'package', '--config', 'Release']
+        if self.options.verbosity > 1:
+            make_args.insert(1, 'VERBOSE=1')
+        print('Building with CMake: "%s"' % (' '.join(make_args),), file=sys.stderr)
+        popen = subprocess.Popen(make_args, cwd=build_dir)
+        out_data, err_data = popen.communicate()
+        if popen.returncode != 0:
+            print('ERROR during make call.', file=sys.stderr)
+            print(out_data, file=sys.stderr)
+            print(err_data, file=sys.stderr)
+            return 1
+        # Copy out archives.
+        self.copyArchives(build_dir)
+        # Remove build directory.
+        if not self.options.keep_co_dir:
+            print('Removing build directory %s' % build_dir, file=sys.stderr)
+            shutil.rmtree(build_dir)
+
+    def tmpDir(self):
+      print('self.tmp_dir = %s' % self.tmp_dir, file=sys.stderr)
+      if self.tmp_dir:
+        if not os.path.exists(self.tmp_dir):
+          os.makedirs(self.tmp_dir)
+        return self.tmp_dir
+      else:
+        return tempfile.mkdtemp()
+
+    def execute(self):
+        """Execute build step."""
+        # Create temporary directory.
+        tmp_dir = self.tmpDir()
+        print('Temporary directory is %s' % (tmp_dir,), file=sys.stderr)
+        # Create Git checkout in temporary directory.
+        checkout_dir = os.path.join(tmp_dir, os.path.basename(self.repository_url))
+        print('Creating checkout in %s' % checkout_dir, file=sys.stderr)
+        git = MinisculeGitWrapper()
+        git.clone(self.repository_url, self.treeish, checkout_dir)
+        # Create build directory.
+        suffix = '-build-%s-%s' % (self.os, self.word_size)
+        build_dir = os.path.join(tmp_dir, os.path.basename(self.repository_url) + suffix)
+        if os.path.exists(build_dir) and not self.options.keep_build_dir:
+            print('Removing build directory %s' % (build_dir,), file=sys.stderr)
+            shutil.rmtree(build_dir)
+        # insert app tags
+        subprocess.call(['../tag-apps.sh', checkout_dir])
+        # Perform the build.  We have to separate between app and whole SeqAn releases.
+        if self.name == 'seqan':
+            self.buildSeqAnRelease(checkout_dir, build_dir)
+        else:
+            self.buildApp(checkout_dir, build_dir)
+        if not self.options.keep_co_dir:
+            print('Removing checkout directory %s' % (checkout_dir,), file=sys.stderr)
+            shutil.rmtree(checkout_dir)
+        # Remove temporary directory again.
+        if self.tmp_dir and not self.options.keep_tmp_dir:
+            # Only remove if not explicitely given and not forced to keep.
+            print('Removing temporary directory %s' % (tmp_dir,), file=sys.stderr)
+            shutil.rmtree(tmp_dir)
+
+
+def workTags(options):
+    """Run the individual steps for tags."""
+    # Get the revisions and tag names.
+    git = MinisculeGitWrapper()
+    #revs_tags = [(rev, tag) for (rev, tag) in git.lsRemote(options.repository_url)
+                 #if re.match(TAG_RE, tag)]
+    tags = [tag for (rev, tag) in git.lsRemote(options.repository_url)
+           if re.match(TAG_RE, tag)]
+    tags.extend(subprocess.check_output(['../tag-apps.sh', os.getcwd(), 'printonly']).split('\n'))
+    # Enumerate all package names that we could enumerate.
+    print('tags = %s' % tags, file=sys.stderr)
+    print('word_sizes = %s' % options.word_sizes, file=sys.stderr)
+    for tag in tags:
+        name, version = tag.rsplit('-v', 1)
+        #version = version[1:]
+        print ('Tag: %s Name: %s Version: %s' % (tag, name, version), file=sys.stdout)
+        for word_size in options.word_sizes.split(','):
+            # Create build step for this package name.
+            pkg_formats = options.package_formats.split(',')
+            build_step = BuildStep(options.package_db, tag, name, version, options.os,
+                                   word_size, pkg_formats, options.repository_url,
+                                   options.make_args.split(), options, options.tmp_dir)
+            # Check whether we need to build this.
+            if not build_step.buildNeeded():
+                continue  # Skip
+            # Execute build step.
+            build_step.execute()
+    return 0
+
+
+def workTrunk(options):
+    """Run the individual steps for the trunk with fake tag name."""
+    # Get the revisions and tag names.
+    git = MinisculeGitWrapper()
+    # Enumerate all package names that we could enumerate.
+    print('fake tag = %s' % options.build_trunk_as, file=sys.stderr)
+    print('word_sizes = %s' % options.word_sizes, file=sys.stderr)
+    name, version = options.build_trunk_as.rsplit('-', 1)
+    version = version[1:]
+    for word_size in options.word_sizes.split(','):
+        # Create build step for this package name.
+        pkg_formats = options.package_formats.split(',')
+        build_step = BuildStep(options.package_db, 'master', name, version, options.os,
+                               word_size, pkg_formats, options.repository_url,
+                               options.make_args.split(), options, options.tmp_dir)
+        # Check whether we need to build this.
+        if not build_step.buildNeeded():
+            continue  # Skip
+        # Execute build step.
+        build_step.execute()
+    return 0
+
+
+def workSrcTar(options):
+    """Build the source tarball."""
+    # Get the revisions and tag names.
+    git = MinisculeGitWrapper()
+    revs_tags = [(rev, tag) for (rev, tag) in git.lsRemote(options.repository_url)
+                 if re.match(TAG_RE, tag)]
+    # Enumerate all package names that we could enumerate.
+    for rev, tag in revs_tags:
+        # Build URL.
+        name, version = tag.rsplit('-', 1)
+        version = version[1:]  # remove prefix "v"
+        if name != 'seqan':
+            continue  # only build source tarballs for seqan
+        # Create destination file name.
+        file_name = '%s-src-%s.tar.gz' % (name, version)
+        dest = os.path.join(options.package_db, '%s-src' % name, file_name)
+        # Check whether we need to rebuild.
+        if os.path.exists(dest):
+            print('Skipping %s; already exists.' % dest, file=sys.stderr)
+            continue
+        # Create temporary directory.
+        if options.tmp_dir:
+            if not os.path.exists(options.tmp_dir):
+                os.makedirs(options.tmp_dir)
+            tmp_dir = options.tmp_dir
+        else:
+            tmp_dir = tempfile.mkdtemp()
+        print('Temporary directory is %s' % tmp_dir, file=sys.stderr)
+        # Create git checkout in temporary directory.
+        checkout_dir = os.path.join(tmp_dir, tag)
+        print('Creating checkout in %s' % checkout_dir, file=sys.stderr)
+        from_ = os.path.join(tmp_dir, file_name)
+        git.clone(options.repository_url, tag, checkout_dir)
+        # Create target directory if it does not exist yet.
+        if not os.path.exists(os.path.dirname(dest)):  # Create directory if necessary.
+            os.makedirs(os.path.dirname(dest))
+        # Create tarball.
+        git.archive(checkout_dir, tag, dest, prefix='%s-%s' % (name, version))
+        # Remove temporary directory again.
+        if tmp_dir and not options.keep_tmp_dir:
+            # Only remove if not explicitely given and not forced to keep.
+            print('Removing temporary directory %s' % (tmp_dir,), file=sys.stderr)
+            shutil.rmtree(tmp_dir)
+    return 0
+
+
+def work(options):
+    """Run the steps."""
+    if options.src_tar:
+        return workSrcTar(options)
+    elif not options.build_trunk_as:
+        return workTags(options)
+    else:
+        return workTrunk(options)
+
+
+def main():
+    """Program entry point."""
+    # Parse Arguments.
+    parser = optparse.OptionParser()
+
+    parser.add_option('-u', '--repository-url', default=REPOSITORY_URL,
+                      help='The git repository URL.', metavar='URL')
+    parser.add_option('--package-db', dest='package_db', type='string',
+                      default=DEFAULT_PACKAGE_DB,
+                      help='Path the directory with the packages.')
+
+    parser.add_option('--src-tar', dest='src_tar', action='store_true',
+                      help='If specified then only the src tarball will be created')
+    parser.add_option('-v', dest='verbosity', action='count', default=1,
+                      help='Increase verbosity.')
+    parser.add_option('--package-formats', dest='package_formats',
+                      default='tar.bz2,zip',
+                      help='Expect the following packages to be created.')
+    parser.add_option('--os', dest='os', help='Expect the packages to be created for this OS.',
+                      default='Linux')
+    parser.add_option('--word-sizes', dest='word_sizes', default='32,64',
+                      help='Build binaries with the given word sizes')
+    parser.add_option('--make-args', dest='make_args', type="string", default='',
+                      help='Arguments for make.')
+    parser.add_option('--tmp-dir', dest='tmp_dir', type='string', default=None,
+                      help='Temporary directory to use. Use this to reuse the same checkout.')
+    parser.add_option('--build-trunk-as', dest='build_trunk_as', type='string', default=None,
+                      help='Build current trunk with this string as a tag name.')
+    parser.add_option('--keep-build-dir', dest='keep_build_dir', default=False,
+                      action='store_true', help='Keep build directory.')
+    parser.add_option('--keep-tmp-dir', dest='keep_tmp_dir', default=False,
+                      action='store_true', help='Keep temporary directory.')
+    parser.add_option('--keep-co-dir', dest='keep_co_dir', default=False,
+                      action='store_true', help='Keep checkout directory.')
+    parser.epilog = ('The program will use the environment variable TMPDIR as '
+                     'the directory for temporary files.')
+
+    options, args = parser.parse_args()
+    if args:
+        parser.error('No arguments expected!')
+        return 1
+
+    options.package_db = os.path.abspath(options.package_db)
+
+    # Fire up work.
+    print('Running SeqAn Auto Builder', file=sys.stderr)
+    return work(options)
diff --git a/util/py_lib/seqan/fixgcov/README b/util/py_lib/seqan/fixgcov/README
new file mode 100644
index 0000000..c3494f3
--- /dev/null
+++ b/util/py_lib/seqan/fixgcov/README
@@ -0,0 +1,22 @@
+gcov Output Fix Tool
+====================
+
+This tool can be used in nightly builds with CMake as follows.
+
+<code>
+export LD_LIBRARY_PATH=/group/ag_abi/software/x86_64/llvm-trunk/lib
+shift
+echo "pwd = `pwd`"
+echo /usr/bin/gcov $*
+/usr/bin/gcov $*
+ret=$?
+dir=$2
+echo find . -name '*.gcov' '>' /tmp/fixgcov.gcov.$$.txt
+find . -name '*.gcov' > /tmp/fixgcov.gcov.$$.txt
+echo grep '\.cpp' `dirname $3`/CXX.includecache
+src=$(grep '\.cpp' `dirname $3`/CXX.includecache)
+inc="-I $HOME/Nightly/`uname -m`/seqan-trunk/include -I $HOME/Nightly/`uname -m`/seqan-trunk/include"
+echo $HOME/Development/seqan-trunk/util/bin/fixgcov.py -s $src --gcov-files=/tmp/fixgcov.gcov.$$.txt -l /tmp/fixgcov.loc.$$.txt $inc
+$HOME/Development/seqan-trunk/util/bin/fixgcov.py -s $src --gcov-files /tmp/fixgcov.gcov.$$.txt -l /tmp/fixgcov.loc.$$.txt $inc
+exit $ret
+</code>
diff --git a/util/py_lib/seqan/fixgcov/__init__.py b/util/py_lib/seqan/fixgcov/__init__.py
new file mode 100755
index 0000000..c9f5931
--- /dev/null
+++ b/util/py_lib/seqan/fixgcov/__init__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python2
+
+import sys
+
+import app
+
+main = app.main
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/util/py_lib/seqan/fixgcov/app.py b/util/py_lib/seqan/fixgcov/app.py
new file mode 100755
index 0000000..22a548c
--- /dev/null
+++ b/util/py_lib/seqan/fixgcov/app.py
@@ -0,0 +1,291 @@
+#!/usr/bin/env python2
+"""Small libclang based app to fix gcov output.
+
+Fix gcov output with templates.  This is done by first parsing in the .cpp files
+(compilation units) with libclang.  The AST is then parsed and all lines within
+composite statements ({ stmt; stmt; ... }) are memoized as 'interesting' lines.
+The resulting interesting lines are serialized to a location file with pickle.
+Finally, gcov output files are read and updated.  If a line is interesting but
+not marked as covered or uncovered (marker '-'), it is marked as uncovered
+(marker '#####').
+
+USAGE: fixgcov.py -i $include_dir -g $gcov_file
+USAGE: fixgcov.py -i $include_dir -s $source_file
+
+Copyright: (c) 2010, Knut Reinert, FU Berlin
+License:   3-clause BSD (see LICENSE)
+"""
+
+from __future__ import with_statement
+
+__author__ = 'Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>'
+
+import optparse
+import os
+import pickle
+import sys
+
+import clang.cindex as ci
+
+
+def _hasFileLocation(node):
+    """Return True if node has a file lcoation."""
+    if not hasattr(node, 'location'):
+        return False
+    if not hasattr(node.location, 'file'):
+        return False
+    if not node.location.file:
+        return False
+    if not hasattr(node.location.file, 'name'):
+        return False
+    if not node.location.file.name:
+        return False
+    return True
+
+
+class CollectCompoundStatementNodeVisitor(object):
+    """Visitor for AST nodes that collects compound statements."""
+    
+    def __init__(self, options):
+        self.options = options
+        self.stack = []
+        self.ranges = []
+    
+    def enterNode(self, node):
+        """Called when a node is entered ("pre-order" traversal)."""
+        self.stack.append(node)
+        ## print '  ' * len(self.stack), node.kind,
+        num_children = len([x for x in node.get_children()])
+        ## if _hasFileLocation(node):
+        ##     print node.location.file.name, '%d-%d' % (node.extent.start.line, node.extent.end.line)
+        ## else:
+        ##     print
+        # Only add range for statements that are no compound statements.  Add
+        # for empty compounds.
+        if not node.kind.is_statement():
+            ## print 'skipping, no statement'
+            return
+        if node.kind == ci.CursorKind.COMPOUND_STMT and num_children > 0:
+            ## print 'skipping, non-empty compound statement', num_children
+            return
+        if node.kind == ci.CursorKind.DECL_STMT:
+            return  # Skip declarations.
+        # Only add if has file location.
+        if _hasFileLocation(node):
+            self.ranges.append((node.location.file.name, node.extent.start.line, node.extent.end.line))
+
+    def exitNode(self, node):
+        """Called when a node is left ("post-order" traversa)."""
+        self.stack.pop()
+
+
+class VisitAllowedRule(object):
+    """Decides whether a AST node and its children is visited."""
+    
+    def __init__(self, options):
+        self.options = options
+        self.include_dirs = [os.path.abspath(x) for x in options.include_dirs]
+        self.cache = {}
+
+    def visitAllowed(self, node):
+        """Return True if visiting is allowed."""
+        # TODO(holtgrew): For this application, stopping at compound statements
+        # would be enough.  Visit if translation unit.
+        if node.kind == ci.CursorKind.TRANSLATION_UNIT:
+            return True
+        # Don't visit if it has no location (built-in).
+        if not _hasFileLocation(node):
+            return False
+        # Try to hit cache.
+        if self.cache.has_key(node.location.file.name):
+            return self.cache[node.location.file.name]
+        # Check whether node's location is below the include directories.  It is
+        # only visited if this is the case.
+        filename = os.path.abspath(node.location.file.name)
+        result = False
+        for x in self.include_dirs:
+            if filename.startswith(x):
+                # print filename, x
+                result = True
+                break
+        self.cache[node.location.file.name] = result  # Save in cache.
+        return result
+
+
+class AstTraverser(object):
+    """Traverses AST tree and applies given visitor object."""
+    
+    def __init__(self, node_visitor, options):
+        self.node_visitor = node_visitor
+        self.options = options
+        self.visit_allowed_rule = VisitAllowedRule(options)
+
+    def _recurse(self, node):
+        """Recursion helper."""
+        if not self.visit_allowed_rule.visitAllowed(node):
+            return False  # We did not visit this node.
+        self.node_visitor.enterNode(node)
+        for c in node.get_children():
+            self._recurse(c)
+        self.node_visitor.exitNode(node)
+        return True
+
+    def run(self, filename):
+        """Main entry point."""
+        index = ci.Index.create()
+        args = ['-I%s' % s for s in self.options.include_dirs]
+        # print args
+        tu = index.parse(filename, args=args)
+        if self.options.verbosity >= 1:
+            print 'Translation unit: %s.' % tu.spelling
+        return self._recurse(tu.cursor)
+    
+    @classmethod
+    def visitFile(klass, filename, node_visitor, options):
+        """Don't instantiate AstTraverser yourself, use this function."""
+        traverser = AstTraverser(node_visitor, options)
+        res = traverser.run(filename)
+        return res == True
+
+
+def main():
+    """Main entry point."""
+    # ========================================================================
+    # Parse command line arguments.
+    # ========================================================================
+    parser = optparse.OptionParser("USAGE: %prog [options] -s file.cpp")
+    parser.add_option('-I', '--include-dir', dest='include_dirs', default=[],
+                      type='string', help='Specify include directories',
+                      action='append')
+    parser.add_option('-s', '--src-file', dest='source_files', default=[],
+                      type='string', help='Specify compilation units.',
+                      action='append')
+    parser.add_option('--src-file-files', dest='source_files_files', default=[],
+                      type='string', help='Specify file with paths to compilation units.',
+                      action='append')
+    parser.add_option('-l', '--location-file', dest='location_file',
+                      default='locations.dat', type='string',
+                      help='Path to file with compound statement locations.')
+    parser.add_option('-g', '--gcov-file', dest='gcov_files', default=[],
+                      type='string', help='Specify gcov files to process.',
+                      action='append')
+    parser.add_option('--gcov-files', dest='gcov_files_files', default=[],
+                      type='string', help='Specify gcov files to process.',
+                      action='append')
+    parser.add_option('-q', '--quiet', dest='verbosity', default=1,
+                      action='store_const', const=0, help='Fewer message.')
+    parser.add_option('-v', '--verbose', dest='verbosity', default=1,
+                      action='store_const', const=2, help='More messages.')
+    options, args = parser.parse_args()
+    if len(args) != 0:
+        parser.error('Incorrect number of arguments!')
+        return 1
+
+    options.include_dirs += [os.path.abspath(os.path.dirname(s)) for s in options.source_files]
+
+    # ========================================================================
+    # Read in files with paths from arguments.
+    # ========================================================================
+
+    for path in options.source_files_files:
+      with open(path, 'rb') as f:
+        options.source_files += [x.strip() for x in f.readlines()]
+    for path in options.gcov_files_files:
+      with open(path, 'rb') as f:
+        options.gcov_files += [x.strip() for x in f.readlines()]
+
+    if not options.source_files and not options.gcov_files:
+        parser.error('Neither source nor gcov file given!')
+        return 1
+
+    # ========================================================================
+    # Collect interesting lines if any source files given.
+    # ========================================================================
+
+    if options.source_files:
+        # If any source file is given, all given source files are parsed and all
+        # lines with compound statements in all included files are written to
+        # the location file.
+        if options.verbosity >= 1:
+            print >>sys.stderr, 'Building Locations'
+        if options.verbosity >= 2:
+            print >>sys.stderr, '=================='
+
+        # Fire off AST traversal.
+        if options.verbosity >= 1:
+            print >>sys.stderr, 'AST Traversal'
+        node_visitor = CollectCompoundStatementNodeVisitor(options)
+        for src in options.source_files:
+            if options.verbosity >= 2:
+                print >>sys.stderr, '  Compilation Unit', src
+            AstTraverser.visitFile(src, node_visitor, options)
+
+        # Convert locations into points.
+        locations = {}
+        for filename, start, stop in node_visitor.ranges:
+            filename = os.path.abspath(filename)
+            for i in range(start, stop + 1):
+                locations.setdefault(filename, set()).add(i)
+
+        # Write out the source locations.
+        if options.verbosity >= 1:
+            print >>sys.stderr, 'Writing out locations to', options.location_file
+        with open(options.location_file, 'wb') as f:
+            pickle.dump(locations, f)
+
+    # ========================================================================
+    # Process GCOV files if any are given.
+    # ========================================================================
+
+    if options.gcov_files:
+        # If no source files and gcov files are given then
+        if options.verbosity >= 1:
+            print >>sys.stderr, 'Updating gcov Results'
+        if options.verbosity >= 2:
+            print >>sys.stderr, '====================='
+
+        if not options.source_files:
+            if options.verbosity >= 1:
+                print >>sys.stderr, 'Loading locations from', options.location_file
+            with open(options.location_file, 'rb') as f:
+                locations = pickle.load(f)
+
+        for filename in options.gcov_files:
+            filename = os.path.abspath(filename)
+            if options.verbosity >= 2:
+                print >>sys.stderr, 'Processing', filename
+            with open(filename, 'rb') as f:
+                lines = f.readlines()
+            pos0 = lines[0].find(':')
+            pos1 = lines[0].find(':', pos0 + 1)
+            source = None
+            result = []
+            skip = False
+            for i, line in enumerate(lines):
+                coverage = line[:pos0]
+                lineno = int(line[pos0 + 1:pos1].strip())
+                slineno = line[pos0 + 1:pos1]
+                txt = line[pos1 + 1:]
+                if txt.startswith('Source:'):
+                    source = os.path.abspath(txt[len('Source:'):].strip())
+                    if not locations.has_key(source):
+                        if options.verbosity >= 2:
+                            print >>sys.stderr, '  Skipping.'
+                        skip = True
+                        break
+                if not source or lineno == 0:
+                    result.append(line)
+                    continue  # Proceed only if in file.
+                if lineno in locations[source] and coverage.strip() == '-':
+                    coverage = ('%%%ds' % pos0) % '#####'
+                result.append(':'.join([coverage, slineno, txt]))
+            # Write back file if not skipped.
+            if skip:
+                continue
+            with open (filename, 'wb') as f:
+              f.write(''.join(result))
+            #print ''.join(result)
+
+# Entry point if called as program.
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/util/py_lib/seqan/paths.py b/util/py_lib/seqan/paths.py
new file mode 100755
index 0000000..0bce2ef
--- /dev/null
+++ b/util/py_lib/seqan/paths.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python2
+"""SeqAn path utilities.
+
+Code to get paths within the SeqAn repository; Useful for setting defaults in
+options.
+
+When called as a program, the paths are printed.
+
+The main assumption is that this module lies in '/util/py_lib/seqan.'
+
+Copyright: (c) 2010, Knut Reinert, FU Berlin
+License:   3-clause BSD (see LICENSE)
+"""
+
+__author__ = 'Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>'
+
+import os
+import os.path
+import sys
+
+def repositoryRoot():
+    """Return path to directory root."""
+    abs_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..'))
+    return os.path.relpath(abs_path, os.getcwd())
+
+def pathToSkeletons():
+    """Return path to '${REPOSITORY}/util/skel'."""
+    return os.path.join(repositoryRoot(), 'util/skel')
+
+def pathToTemplate(template, filename):
+    """Return path to file with given name in given template."""
+    return os.path.join(pathToSkeletons(), template, filename)
+
+def pathToApp(location, app):
+    """Return path to the app in the given location/repository."""
+    return os.path.join(repositoryRoot(), location, 'apps', app)
+
+def pathToInclude(location):
+    """Return path to the include dir in the given location/repository."""
+    return os.path.join(repositoryRoot(), location, 'include')
+
+def pathToDemo(location, demo):
+    """Return path to the demo file in the given location/repository."""
+    return os.path.join(repositoryRoot(), location, 'demos', '%s.cpp' % demo)
+
+def pathToTest(location, test):
+    """Return path to the test in the given location/repository."""
+    return os.path.join(repositoryRoot(), location, 'tests', test)
+
+def pathToRepository(location):
+    """Return path to the given location/repository."""
+    return os.path.join(repositoryRoot(), location)
+
+def pathToHeader(location, filename):
+    """Return path to the given header - just concatenate."""
+    return os.path.join(repositoryRoot(), location, filename)
+
+def main(args):
+    print 'SeqAn paths'
+    print
+    print 'repositoryRoot()   ==', repositoryRoot()
+    print 'pathToSkeletons() ==', pathToSkeletons()
+
+if __name__ == '__main__':
+   sys.exit(main(sys.argv))
diff --git a/util/py_lib/seqan/pyclangcheck/__init__.py b/util/py_lib/seqan/pyclangcheck/__init__.py
new file mode 100755
index 0000000..c9f5931
--- /dev/null
+++ b/util/py_lib/seqan/pyclangcheck/__init__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python2
+
+import sys
+
+import app
+
+main = app.main
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/util/py_lib/seqan/pyclangcheck/app.py b/util/py_lib/seqan/pyclangcheck/app.py
new file mode 100755
index 0000000..aa6d0cf
--- /dev/null
+++ b/util/py_lib/seqan/pyclangcheck/app.py
@@ -0,0 +1,322 @@
+#!/usr/bin/env python2
+"""pyclangcheck driver code
+
+This code is the driver code for the pyclangcheck tool.
+
+Copyright: (c) 2010, Knut Reinert, FU Berlin
+License:   3-clause BSD (see LICENSE)
+"""
+
+from __future__ import with_statement
+
+__author__ = 'Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>'
+
+import datetime
+import optparse
+import os
+import os.path
+import sys
+
+import clang.cindex as ci
+
+import simple_checks
+import violations
+import rules
+
+def _hasFileLocation(node):
+    """Return True if node has a file lcoation."""
+    if hasattr(node, '_has_file_location'):
+        return node._has_file_location
+    if not hasattr(node, 'location'):
+        node._has_file_location = False
+        return False
+    if not hasattr(node.location, 'file'):
+        node._has_file_location = False
+        return False
+    if not node.location.file:
+        node._has_file_location = False
+        return False
+    if not hasattr(node.location.file, 'name'):
+        node._has_file_location = False
+        return False
+    if not node.location.file.name:
+        node._has_file_location = False
+        return False
+    node._has_file_location = True
+    return True
+
+
+class FileCache(object):
+    def __init__(self):
+        self.cache = {}
+
+    def get(self, path):
+        if self.cache.has_key(path):
+            return self.cache[path]
+        with open(path, 'rb') as f:
+            fcontents = f.readlines()
+        self.cache[path] = fcontents
+        return self.cache[path]
+
+
+class CollectViolationsVisitor(object):
+    """Visitor for AST nodes that collects rule violations."""
+    
+    def __init__(self, options, rules):
+        self.options = options
+        self.rules = rules
+        for rule in self.rules:
+            rule.visitor = self
+        self.stack = []
+        self.violations = {}
+        self.file_cache = FileCache()
+        self.class_stack = []
+        self.seen_files = set()
+        self.blocked_files = set()
+   
+    def seenToBlocked(self):
+        """Move seen files to blocked files."""
+        self.blocked_files |= self.seen_files
+
+    def enterNode(self, node):
+        """Called when a node is entered ("pre-order" traversal)."""
+        self.stack.append(node)
+        ck = ci.CursorKind
+        if node.kind in [ck.CLASS_TEMPLATE, ck.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, ck.CLASS_DECL]:
+            ## print 'PUSH CLASS', node.spelling
+            self.class_stack.append(node)
+
+        # Mark file as seen for nodes that are directly below the compilation unit.
+        if len(self.stack) <= 2 and _hasFileLocation(node):
+            self.seen_files.add(node.location.file.name)
+        
+        if self.options.verbosity >= 2:
+            if node.extent.start.file:
+                filename = node.extent.start.file.name
+                lines = self.file_cache.get(filename)
+                start = "%s:%d:%d" % (os.path.basename(filename), node.extent.start.line-1, node.extent.start.column-1)
+                end = "%s:%d:%d" % ('#', node.extent.end.line-1, node.extent.end.column-1)
+                lines = [x for x in lines[node.extent.start.line-1:node.extent.end.line]]
+                if len(lines) == 1:
+                    lines[0] = lines[0][node.extent.start.column - 1:node.extent.end.column-1]
+                else:
+                    lines[0] = lines[0][node.extent.start.column - 1:]
+                    lines[-1] = lines[-1][:node.extent.end.column-1]
+                if len(lines) > 1:
+                    txt = '<multiline>'
+                else:
+                    txt = ''.join(lines).replace('\n', '\\n')
+                print '  ' * len(self.stack), 'Entering', node.kind, node._kind_id, node.spelling, 'txt="%s"' % txt, "%s-%s" % (start, end)
+        violations = []
+        for rule in self.rules:
+            if rule.allowVisit(node):
+                #print ' ', ' ' * len(self.stack), 'Checking rule', rule.rule_id
+                vs = rule.check(node)
+                ## if self.options.verbosity >= 2:
+                ##     for v in vs:
+                ##         print 'VIOLATION', v
+                violations += vs
+        for v in violations:
+            ## if self.options.verbosity >= 2:
+            ##     print v
+            self.violations[v.key()] = v
+
+    def exitNode(self, node):
+        """Called when a node is left ("post-order" traversa)."""
+        self.stack.pop()
+        if self.class_stack and self.class_stack[-1] is node:
+            ## print 'POP CLASS', node.spelling
+            self.class_stack.pop()
+
+    def getCurrentClassName(self):
+        """Returns name of current class."""
+        if not self.class_stack:
+            ## print 'CURRENT CLASS', None
+            return None
+        ## print 'CURRENT CLASS', self.class_stack[-1].spelling
+        return self.class_stack[-1].spelling
+
+
+class VisitAllowedRule(object):
+    """Decides whether a AST node and its children is visited."""
+    
+    def __init__(self, options, blocked_files):
+        self.options = options
+        self.include_dirs = [os.path.abspath(x) for x in options.include_dirs]
+        self.cache = {}
+        self.blocked_files = blocked_files
+
+    def visitAllowed(self, node):
+        """Return True if visiting is allowed."""
+        # Visit if translation unit.
+        if node.kind == ci.CursorKind.TRANSLATION_UNIT:
+            return True
+        # Don't visit if it has no location (built-in).
+        if not _hasFileLocation(node):
+            return False
+        # Try to hit cache.
+        if self.cache.has_key(node.location.file.name):
+            return self.cache[node.location.file.name]
+        # Check whether the file is blocked.
+        if node.location.file.name in self.blocked_files:
+            # print 'Blocked', node.location.file.name
+            self.cache[node.location.file.name] = False
+            return False
+        # Check whether node's location is below the include directories.  It is
+        # only visited if this is the case.
+        filename = os.path.abspath(node.location.file.name)
+        result = False
+        for x in self.include_dirs:
+            if filename.startswith(x):
+                # print filename, x
+                result = True
+                break
+        self.cache[node.location.file.name] = result  # Save in cache.
+        return result
+
+
+class AstTraverser(object):
+    """Traverses AST tree and applies given visitor object."""
+    
+    def __init__(self, node_visitor, options):
+        self.node_visitor = node_visitor
+        self.options = options
+        self.visit_allowed_rule = VisitAllowedRule(options, node_visitor.blocked_files)
+
+    def _recurse(self, node):
+        """Recursion helper."""
+        if not self.visit_allowed_rule.visitAllowed(node):
+            return False  # We did not visit this node.
+        self.node_visitor.enterNode(node)
+        for c in node.get_children():
+            self._recurse(c)
+        self.node_visitor.exitNode(node)
+        return True
+
+    def run(self, filename):
+        """Main entry point."""
+        index = ci.Index.create()
+        args = ['-I%s' % s for s in self.options.include_dirs]
+        # print args
+        tu = index.parse(filename, args=args)
+        if self.options.verbosity >= 1:
+            print 'Translation unit: %s.' % tu.spelling
+        return self._recurse(tu.cursor)
+    
+    @classmethod
+    def visitFile(klass, filename, node_visitor, options):
+        """Don't instantiate AstTraverser yourself, use this function."""
+        if options.verbosity >= 1:
+            print >>sys.stderr, 'Checking', filename
+        traverser = AstTraverser(node_visitor, options)
+        res = traverser.run(filename)
+        return res != True
+
+
+def main():
+    # ========================================================================
+    # Parse command line arguments.
+    # ========================================================================
+    parser = optparse.OptionParser("USAGE: %prog [options] file.cpp")
+    parser.add_option('-s', '--source-file', dest='source_files', default=[],
+                      type='string', help='Specify source (.cpp) files.',
+                      action='append')
+    parser.add_option('-S', '--source-file-file', dest='source_file_files', default=[],
+                      type='string', help='File with path to source files.',
+                      action='append')
+    parser.add_option('-i', '--include-dir', dest='include_dirs', default=[],
+                      type='string', help='Specify include directories',
+                      action='append')
+    parser.add_option('-e', '--exclude-dir', dest='exclude_dirs', default=[],
+                      type='string', help='Violations in these directories are not shown.',
+                      action='append')
+    parser.add_option('-q', '--quiet', dest='verbosity', default=1,
+                      action='store_const', const=0, help='Fewer message.')
+    parser.add_option('-v', '--verbose', dest='verbosity', default=1,
+                      action='store_const', const=2, help='More messages.')
+    parser.add_option('--ignore-nolint', dest='ignore_nolint', default=False,
+                      action='store_const', const=True, help='Ignore // nolint statements.')
+    parser.add_option('--dont-show-source', dest='show_source', default=True,
+                      action='store_const', const=False, help='Suppress source line display')
+    options, args = parser.parse_args()
+
+    if len(args) != 0:
+        parser.error('Incorrect number of arguments!')
+        return 1
+
+    # Load source files given in file of paths.
+    for filename in options.source_file_files:
+        with open(filename, 'rb') as f:
+            options.source_files += [x.strip() for x in f.readlines()]
+
+    # ========================================================================
+    # Setup traversal.
+    # ========================================================================
+
+    # Recursion Rule: Only check symbols within the include directories.
+    recurse_rules = []
+    recurse_rules.append(rules.InIncludeDirsRule(options.include_dirs, options.exclude_dirs, options.source_files))
+    # Define symbol naming rules.
+    R = rules.GenericSymbolNameRule
+    r = rules
+    ck = ci.CursorKind
+    check_rules = [
+        R(ck.STRUCT_DECL                          , r.RE_STRUCT       , r.RULE_NAMING_STRUCT                ),
+        R(ck.UNION_DECL                           , r.RE_TYPE         , r.RULE_NAMING_UNION                 ),
+        R(ck.CLASS_DECL                           , r.RE_TYPE         , r.RULE_NAMING_CLASS                 ),
+        R(ck.ENUM_DECL                            , r.RE_TYPE         , r.RULE_NAMING_ENUM                  ),
+        R(ck.FIELD_DECL                           , r.RE_VARIABLE     , r.RULE_NAMING_FIELD                 ),
+        R(ck.ENUM_CONSTANT_DECL                   , r.RE_CONSTANT     , r.RULE_NAMING_ENUM_CONSTANT         ),
+        R(ck.FUNCTION_DECL                        , r.RE_FUNCTION     , r.RULE_NAMING_FUNCTION              ),
+        R(ck.PARM_DECL                            , r.RE_VARIABLE     , r.RULE_NAMING_PARAMETER             ),
+        R(ck.TYPEDEF_DECL                         , r.RE_TYPE         , r.RULE_NAMING_TYPEDEF               ),
+        R(ck.CXX_METHOD                           , r.RE_FUNCTION     , r.RULE_NAMING_CXX_METHOD            ),
+        R(ck.TEMPLATE_TYPE_PARAMETER              , r.RE_TYPE         , r.RULE_NAMING_TPL_TYPE_PARAMETER    ),
+        R(ck.TEMPLATE_NON_TYPE_PARAMETER          , r.RE_CONSTANT     , r.RULE_NAMING_TPL_NON_TYPE_PARAMETER),
+        R(ck.TEMPLATE_TEMPLATE_PARAMTER           , r.RE_TYPE         , r.RULE_NAMING_TPL_TPL_PARAMETER     ),
+        #R(ck.FUNCTION_TEMPLATE                    , r.RE_FUNCTION     , r.RULE_NAMING_FUNCTION_TPL          ),
+        R(ck.CLASS_TEMPLATE                       , r.RE_TYPE_TEMPLATE, r.RULE_NAMING_CLASS_TPL             ),
+        R(ck.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, r.RE_TYPE_TEMPLATE, r.RULE_NAMING_CLASS_TPL_SPEC        ),
+        rules.FunctionTemplateRule(),
+        rules.VariableNameRule(),
+    ]
+
+    # ========================================================================
+    # Perform traversal.
+    # ========================================================================
+
+    node_visitor = CollectViolationsVisitor(options, check_rules)
+    for filename in options.source_files:
+        start = datetime.datetime.now()
+        res = AstTraverser.visitFile(filename, node_visitor, options)
+        node_visitor.seenToBlocked()
+        elapsed = datetime.datetime.now() - start
+        print >>sys.stderr, '  took', elapsed.seconds, 's'
+        if res:
+            break
+
+    # ========================================================================
+    # Dumber checks (e.g. whitespace at end of file).
+    # ========================================================================
+
+    checkers = [simple_checks.WhitespaceChecker(),
+                simple_checks.CommentChecker()]
+    vs = {}
+    for filename in node_visitor.seen_files:
+        for checker in checkers:
+            vs.update(checker.check(filename))
+
+    # ========================================================================
+    # Print violations.
+    # ========================================================================
+
+    print 'VIOLATIONS'
+    vs.update(node_visitor.violations)
+    printer = violations.ViolationPrinter(options.ignore_nolint,
+                                          options.show_source)
+    printer.show(vs)
+    return len(vs) > 0
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/util/py_lib/seqan/pyclangcheck/rules.py b/util/py_lib/seqan/pyclangcheck/rules.py
new file mode 100755
index 0000000..15c8d33
--- /dev/null
+++ b/util/py_lib/seqan/pyclangcheck/rules.py
@@ -0,0 +1,201 @@
+#!/usr/bin/env python2
+
+__author__ = 'Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>'
+
+import os.path
+import re
+
+import clang.cindex as ci
+
+import app
+import violations
+
+RULE_NAMING_CONSTANT = 'naming.constant'
+RULE_NAMING_STRUCT = 'naming.struct'
+RULE_NAMING_UNION = 'naming.union'
+RULE_NAMING_CLASS = 'naming.class'
+RULE_NAMING_ENUM = 'naming.enum'
+RULE_NAMING_FIELD = 'naming.field'
+RULE_NAMING_ENUM_CONSTANT = 'naming.enum_constant'
+RULE_NAMING_VARIABLE = 'naming.variable'
+RULE_NAMING_FUNCTION = 'naming.function'
+RULE_NAMING_PARAMETER = 'naming.parameter'
+RULE_NAMING_VARIABLE = 'naming.variable'
+RULE_NAMING_CXX_METHOD = 'naming.method'
+RULE_NAMING_TYPEDEF = 'naming.typedef'
+RULE_NAMING_TPL_NON_TYPE_PARAMETER = 'naming.tpl_nontype_param'
+RULE_NAMING_TPL_TYPE_PARAMETER = 'naming.tpl_type_param'
+RULE_NAMING_TPL_TPL_PARAMETER = 'naming.tpl_tpl_param'
+RULE_NAMING_FUNCTION_TPL = 'naming.function_tpl'
+RULE_NAMING_CLASS_TPL = 'naming.class_tpl'
+RULE_NAMING_CLASS_TPL_SPEC = 'naming.class_tpl_spec'
+
+RE_CONSTANT = r'^[A-Z]([_A-Z0-9])*_*$'
+RE_VARIABLE = r'^_?[a-z]([_a-zA-Z0-9])*_*$'
+RE_FUNCTION = r'operator.*|^_?[a-z]([_a-zA-Z0-9])*\(.*\)_*$'
+RE_TYPE = r'^[A-Z]([a-zA-Z0-9])*_*$'
+RE_TYPE_TEMPLATE = r'^[A-Z]([a-zA-Z0-9])*_*<.*>$'
+RE_STRUCT = r'^[A-Z]([a-zA-Z0-9])*_*(<.*>)?$'
+
+RULE_TEXTS = {
+    RULE_NAMING_CONSTANT: 'Constant names must be all upper-case, separated by underscores.',
+    RULE_NAMING_STRUCT: 'Struct names must be all camel case, starting with upper case.',
+    RULE_NAMING_UNION: 'Union names must be all camel case, starting with upper case.',
+    RULE_NAMING_CLASS: 'Class names must be all camel case, starting with upper case.',
+    RULE_NAMING_ENUM: 'Enum names must be all camel case, starting with upper case.',
+    RULE_NAMING_FIELD: 'Field names must be camel case case, starting with lower case.',
+    RULE_NAMING_ENUM_CONSTANT: 'Enum constant names must be all upper-case, separated by underscores.',
+    RULE_NAMING_VARIABLE: 'Variable names must be camel case case, starting with lower case.',
+    RULE_NAMING_FUNCTION: 'Function names must be camel case case, starting with lower case.',
+    RULE_NAMING_PARAMETER: 'Parameter names must be camel case case, starting with lower case.',
+    RULE_NAMING_CXX_METHOD: 'Method names must be camel case case, starting with lower case.',
+    RULE_NAMING_TYPEDEF: 'Typedef names must be all camel case, starting with upper case.',
+    RULE_NAMING_TPL_NON_TYPE_PARAMETER: 'Template non-type parameters must be all upper-case, separated by underscores.',
+    RULE_NAMING_TPL_TYPE_PARAMETER: 'Template type parameter names must be all camel case, starting with upper case.',
+    RULE_NAMING_TPL_TPL_PARAMETER: 'Template template parameter names must be all camel case, starting with upper case.',
+    RULE_NAMING_FUNCTION_TPL: 'Function template names must be camel case case, starting with lower case.',
+    RULE_NAMING_CLASS_TPL: 'Class template names must be all camel case, starting with upper case.',
+    RULE_NAMING_CLASS_TPL_SPEC: 'Partial specialization names must be all camel case, starting with upper case.',
+}
+
+
+class GenericSymbolNameRule(object):
+    def __init__(self, kind, regular_ex, rule_name):
+        self.kind = kind
+        self.regular_ex = regular_ex
+        self.rule_name = rule_name
+        self.visitor = None
+
+    def allowVisit(self, node):
+        if not app._hasFileLocation(node):
+            #print 'no location'
+            return False
+        if not node.displayname:
+            #print 'no displayname'
+            return False  # Ignore empty symbols.
+        # print 'allow visit template type?', displayname, node.kind
+        if node.kind == self.kind:
+            #print 'different kind'
+            return True
+        return False
+    
+    def check(self, node):
+        displayname = node.displayname
+        #print 'checking', displayname
+        #import pdb; pdb.set_trace()
+        if not re.match(self.regular_ex, displayname):
+            v = violations.RuleViolation(
+                self.rule_name, displayname, node.location.file.name,
+                node.location.line, node.location.column)
+            return [v]
+        return []
+
+
+class VariableNameRule(object):
+    """Checks variable names (in variable declarations).
+
+    The name must either be camel case (starting with lower case character) or
+    all upper case.
+    """
+
+    def __init__(self):
+        self.visitor = None
+
+    def allowVisit(self, node):
+        if not app._hasFileLocation(node):
+            return False
+        displayname = node.displayname
+        if not displayname:
+            return False  # Ignore empty symbols.
+        if node.kind == ci.CursorKind.VAR_DECL:
+            return True
+        return False
+
+    def check(self, node):
+        displayname = node.displayname
+        if not re.match(RE_VARIABLE, displayname) and not re.match(RE_CONSTANT, displayname):
+            # TODO(holtgrew): Only allow RE_CONSTANT if 'const' in declaration type.
+            v = violations.RuleViolation(
+                RULE_NAMING_VARIABLE, displayname, node.location.file.name,
+                node.location.line, node.location.column)
+            return [v]
+        return []
+
+
+class FunctionTemplateRule(object):
+    """Checks function templates.
+
+    Function template have to follow the function naming scheme.  However,
+    libclang also exposes constructors with kind function template.  The visitor
+    keeps a stack of current classes so we look whether the current class or
+    class template has the same name as the function template and allow this
+    besides the function naming scheme.
+    """
+
+    def __init__(self):
+        self.visitor = None
+
+    def allowVisit(self, node):
+        if not app._hasFileLocation(node):
+            return False
+        displayname = node.displayname
+        if not displayname:
+            return False  # Ignore empty symbols.
+        if node.kind == ci.CursorKind.FUNCTION_TEMPLATE:
+            return True
+        return False
+
+    def check(self, node):
+        displayname = node.displayname
+        if not re.match(RE_FUNCTION, displayname):
+            up_to_bracket = displayname[:displayname.find('<')]
+            ## print 'CHECK', self.visitor.getCurrentClassName(), '!=?', up_to_bracket
+            if self.visitor.getCurrentClassName() != up_to_bracket:
+                v = violations.RuleViolation(
+                    RULE_NAMING_FUNCTION_TPL, displayname, node.location.file.name,
+                    node.location.line, node.location.column)
+                return [v]
+        return []
+
+
+class InIncludeDirsRule(object):
+    """Rule to block visiting and recursion outside include dirs."""
+    
+    def __init__(self, include_dirs, exclude_dirs, source_files):
+        self.include_dirs = [os.path.abspath(x) for x in include_dirs]
+        self.source_files = [os.path.abspath(x) for x in source_files]
+        self.exclude_dirs = [os.path.abspath(x) for x in exclude_dirs]
+        self.cache = {}
+    
+    def allowVisit(self, node):
+        """Return True if visiting is allowed."""
+        if node.kind == ci.CursorKind.TRANSLATION_UNIT:
+            return True
+        if not app._hasFileLocation(node):
+            return False
+        if self.cache.has_key(node.location.file.name):
+            return self.cache[node.location.file.name]
+        # Check whether node's location is below the include directories or one
+        # of the source files.
+        filename = os.path.abspath(node.location.file.name)
+        result = False
+        for x in self.include_dirs:
+            if filename.startswith(x):
+                result = True
+                break
+        if not result:
+            for x in self.source_files:
+                if filename == x:
+                    result = True
+                    break
+        if result:
+            for x in self.exclude_dirs:
+                if filename.startswith(x):
+                    result = False
+                    break
+        self.cache[node.location.file.name] = result
+        return result
+    
+    def allowRecurse(self, node):
+        """Return True if we want to recurse below node."""
+        return self.allowVisit(node)
diff --git a/util/py_lib/seqan/pyclangcheck/simple_checks.py b/util/py_lib/seqan/pyclangcheck/simple_checks.py
new file mode 100755
index 0000000..b39a4aa
--- /dev/null
+++ b/util/py_lib/seqan/pyclangcheck/simple_checks.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python2
+"""Simple source code checks, e.g. trailing whitespace."""
+
+from __future__ import with_statement
+
+import bisect
+import re
+import sys
+
+import violations
+
+RULE_TRAILING_WHITESPACE = 'whitespace.trailing'
+RULE_TEXT_TRAILING_WHITESPACE = 'Trailing whitespace is not allowed.'
+ 
+RULE_TODO_ONE_SPACE = 'whitespace.todo'
+RULE_TEXT_TODO_ONE_SPACE= 'There should be exactly one space before TODO.'
+
+RULE_TODO_USERNAME = 'readability.todo'
+RULE_TEXT_TODO_USERNAME = 'TODO comments should look like this: "// TODO(username): Text".'
+
+RULE_TODO_SPACE_AFTER = 'whitespace.todo'
+RULE_TEXT_TODO_SPACE_AFTER = '"TODO (username):" should be followed by a space.'
+
+RE_TODO = r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?'
+
+class WhitespaceChecker(object):
+    """Performs simple white space checks."""
+
+    # TODO(holtgrew): Do not allow tabs.
+
+    def check(self, filename):
+        vs = []
+        with open(filename, 'rb') as f:
+            line_no = 0
+            for line in f:
+                line_no += 1
+                if line.rstrip() == line.rstrip('\r\n'):
+                    continue
+                v = violations.SimpleRuleViolation(
+                    RULE_TRAILING_WHITESPACE, filename, line_no,
+                    len(line.rstrip()) + 1, RULE_TEXT_TRAILING_WHITESPACE)
+                vs.append(v)
+        return dict([(v.key(), v) for v in vs])
+
+
+class SourceFile(object):
+    def __init__(self, name):
+        self.name = name
+
+
+class SourceLocation(object):
+    def __init__(self, filename, line, column, offset):
+        self.file = SourceFile(filename)
+        self.line = line
+        self.column = column
+        self.offset = offset
+
+    def __str__(self):
+        return '%s:%d/%d (@%d)' % (self.file.name, self.line, self.column,
+                                   self.offset)
+
+    def __repr__(self):
+        return str(self)
+
+
+def enumerateComments(filename):
+    # Read file.
+    with open (filename, 'rb') as f:
+        lines = f.readlines()
+        fcontents = ''.join(lines)
+    # Build line break index.
+    line_starts = [0]
+    for line in lines:
+        line_starts.append(line_starts[-1] + len(line))
+    #print line_starts
+    # Search for all comments.
+    pattern = re.compile(
+        r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
+        re.DOTALL | re.MULTILINE)
+    for match in re.finditer(pattern, fcontents):
+        line_start = bisect.bisect(line_starts, match.start(0))
+        line_end = bisect.bisect(line_starts, match.end(0) - 1)
+        column_start = match.start(0) - line_starts[line_start - 1]
+        column_end = match.end(0) - line_starts[line_end - 1]
+        yield (SourceLocation(filename, line_start, column_start + 1, match.start(0)),
+               SourceLocation(filename, line_end, column_end + 1, match.end(0)),
+               match.group(0))
+
+
+class CommentChecker(object):
+    """Performs the checks on comments."""
+
+    def check(self, filename):
+        vs = []
+        for cstart, cend, comment in enumerateComments(filename):
+            if comment.startswith('//'):
+                # Check TODO comments.
+                match = re.match(RE_TODO, comment)
+                if match:
+                    if len(match.group(1)) > 1:
+                        print comment
+                        v = violations.SimpleRuleViolation(
+                            RULE_TODO_ONE_SPACE, filename, cstart.line,
+                            cstart.column, RULE_TEXT_TODO_ONE_SPACE)
+                        vs.append(v)
+                    if not match.group(2):
+                        v = violations.SimpleRuleViolation(
+                            RULE_TODO_USERNAME, filename, cstart.line,
+                            cstart.column, RULE_TEXT_TODO_USERNAME)
+                        vs.append(v)
+                    if match.group(3) != ' ' and match.group(3) != '':
+                        v = violations.SimpleRuleViolation(
+                            RULE_TODO_SPACE_AFTER, filename, cstart.line,
+                            cstart.column, RULE_TEXT_TODO_SPACE_AFTER)
+                        vs.append(v)
+        return dict([(v.key(), v) for v in vs])
+
diff --git a/util/py_lib/seqan/pyclangcheck/suppressions.py b/util/py_lib/seqan/pyclangcheck/suppressions.py
new file mode 100755
index 0000000..18ff536
--- /dev/null
+++ b/util/py_lib/seqan/pyclangcheck/suppressions.py
@@ -0,0 +1 @@
+#!/usr/bin/env python2
diff --git a/util/py_lib/seqan/pyclangcheck/violations.py b/util/py_lib/seqan/pyclangcheck/violations.py
new file mode 100755
index 0000000..f91b8fb
--- /dev/null
+++ b/util/py_lib/seqan/pyclangcheck/violations.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python2
+"""Code related to violations and suppressions."""
+
+from __future__ import with_statement
+
+import os
+import os.path
+import sys
+
+import app
+import rules
+
+
+class RuleViolation(object):
+    def __init__(self, rule_id, violator, file, line, column):
+        self.rule_id = rule_id
+        self.violator = violator
+        self.file = file
+        self.line = line
+        self.column = column
+    
+    def key(self):
+        return (self.file, self.line, self.column, self.rule_id, self.violator)
+    
+    def __str__(self):
+        msg = '[%s:%d/%d] %s "%s": %s'
+        return msg % ('/'.join(self.file.split('/')[-2:]), self.line, self.column,
+                      self.rule_id, self.violator, rules.RULE_TEXTS[self.rule_id])
+
+
+class SimpleRuleViolation(object):
+    def __init__(self, rule_id, file, line, column, msg):
+        self.rule_id = rule_id
+        self.file = file
+        self.line = line
+        self.column = column
+        self.msg = msg
+    
+    def key(self):
+        return (self.file, self.line, self.column, self.rule_id)
+    
+    def __str__(self):
+        msg = '[%s:%d/%d] %s : %s'
+        return msg % ('/'.join(self.file.split('/')[-2:]), self.line, self.column,
+                      self.rule_id, self.msg)
+
+
+class NolintManager(object):
+    """Manage the lines ending in '//nolint'."""
+
+    def __init__(self):
+        self.locations = {}
+
+    def hasNolint(self, filename, lineno):
+        filename = os.path.abspath(filename)
+        # Ensure that the nolint lines are registered in self.locations[filename].
+        if not self.locations.has_key(filename):
+            line_set = set()
+            with open(filename, 'rb') as f:
+                line_no = 0
+                for line in f:
+                    line_no += 1
+                    if line.strip().endswith('// nolint'):
+                        ## print 'nolint', filename, line_no
+                        line_set.add(line_no)
+            self.locations[filename] = line_set
+        # Query self.locations[filename].
+        return lineno in self.locations[filename]
+
+
+class ViolationPrinter(object):
+    def __init__(self, ignore_nolint, show_source):
+      self.nolints = NolintManager()
+      self.file_cache = app.FileCache()
+      self.ignore_nolint = ignore_nolint
+      self.show_source = show_source
+
+    def show(self, vs):
+        previous = None
+        for k in sorted(vs.keys()):
+            violation = vs[k]
+            if self.ignore_nolint or not self.nolints.hasNolint(violation.file, violation.line):
+                print violation
+                line = self.file_cache.get(violation.file)[violation.line - 1]
+                if self.show_source:
+                    print line.rstrip()
+                    print '%s^' % (' ' * (violation.column - 1))
+                    print
+            previous = violation
+        print 'Total: %d violations' % len(vs)
+
diff --git a/util/py_lib/seqan/seqan.css b/util/py_lib/seqan/seqan.css
new file mode 100644
index 0000000..ac38d89
--- /dev/null
+++ b/util/py_lib/seqan/seqan.css
@@ -0,0 +1,7 @@
+html .vlist {
+	border: none;
+	}
+
+table {
+	width: 100%;
+	}
\ No newline at end of file
diff --git a/util/py_lib/seqan/seqan.html b/util/py_lib/seqan/seqan.html
new file mode 100644
index 0000000..07015b4
--- /dev/null
+++ b/util/py_lib/seqan/seqan.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en-EN">
+    <head>
+        <title>Sub Page | SeqAn</title>
+        <!-- Meta Tags --> 
+        <meta http-equiv="X-UA-Compatible" content="IE=9">
+        <!-- Enable IE9 Standards mode --> <!-- WordPress --> 
+        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+        <meta http-equiv="content-script-type" content="text/javascript">
+        <meta name="keywords" content="">
+        <meta name="language" content="en">
+        <meta name="content-language" content="en">
+        <meta name="publisher" content="SeqAn">
+        <meta name="revisit-after" content="1 days">
+        <meta name="author" content="FU Berlin - http://www.fu-berlin.de">
+        <meta name="description" content=" - The C++ template library for sequence analysis.">
+        <!-- FU Berlin Layout --> 
+        <meta http-equiv="cache-control" content="no-cache">
+        <meta http-equiv="pragma" content="no-cache">
+        <meta name="robots" content="index, follow">
+        <meta name="geo.region" content="DE-BE">
+        <meta name="geo.placename" content="Berlin">
+        <!-- CSS --> 
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/style.css" media="" rel="stylesheet" type="text/css">
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/yaml_base.css" media="" rel="stylesheet" type="text/css">
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/nav_hlist.css" media="" rel="stylesheet" type="text/css">
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/nav_vlist.css" media="" rel="stylesheet" type="text/css">
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/basemod_fu_berlin.css" media="" rel="stylesheet" type="text/css">
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/content_fu.css" media="" rel="stylesheet" type="text/css">
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/yaml_print_base.css" media="" rel="stylesheet" type="text/css">
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/print.css" media="" rel="stylesheet" type="text/css">
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/yaml_forms.css" media="" rel="stylesheet" type="text/css">
+        <!--[if lte IE 7]> 
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/yaml_iehacks.css" media="" rel="stylesheet" type="text/css" />
+        <link href="http://www.seqan.de/wp-content/themes/fub-theme/styles/patch.css" media="" rel="stylesheet" type="text/css" />
+        <![endif]--> <!-- Favicon, RSS Links --> 
+        <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://www.seqan.de/feed/">
+        <link rel="Shortcut Icon" type="image/x-icon" href="http://www.seqan.de/wp-content/uploads/2012/01/favicon.png">
+        <link rel="pingback" href="http://www.seqan.de/xmlrpc.php">
+        <link rel="stylesheet" id="wp_dlmp_styles-css" href="http://www.seqan.de/wp-content/plugins/download-monitor/page-addon/styles.css?ver=3.5.1" type="text/css" media="all">
+        <link rel="stylesheet" id="page-list-style-css" href="http://www.seqan.de/wp-content/plugins/page-list/css/page-list.css?ver=4.2" type="text/css" media="all">
+        <link rel="stylesheet" id="counterize_stylesheet-css" href="http://www.seqan.de/wp-content/plugins/counterize/counterize.css.php?ver=3.5.1" type="text/css" media="all">
+        <script type="text/javascript" src="http://www.seqan.de/wp-content/plugins/counterize/counterize.js.php?ver=3.5.1"></script> 
+        <link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www.seqan.de/xmlrpc.php?rsd">
+        <link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://www.seqan.de/wp-includes/wlwmanifest.xml">
+        <link rel="next" title="News" href="http://www.seqan.de/news/">
+        <meta name="generator" content="WordPress 3.5.1">
+        <link rel="canonical" href="http://www.seqan.de/">
+        <style type="text/css"> .download-info .download-button { background-image: url(http://www.seqan.de/wp-content/plugins/download-monitor/page-addon/downloadbutton.gif); } .download-info .more-button { background-image: url(http://www.seqan.de/wp-content/plugins/download-monitor/page-addon/morebutton.gif); } </style>
+        <link href="seqan.css" media="" rel="stylesheet" type="text/css">
+    </head>
+    <body>
+        <div class="page_margins gradient">
+            <div class="page">
+                <!-- Header --> 
+                <div id="header">
+                    <a accesskey="O" name="seitenanfang" id="seitenanfang"></a> <a href="http://www.seqan.de" accesskey="H"><img id="fu_logo" title="To the Homepage of SeqAn" src="http://www.seqan.de/wp-content/uploads/2012/02/seqan_logo_167x110.png" height="110"></a> 
+                    <h1 class="hideme">SeqAn</h1>
+                    <hr class="hideme">
+                    <div id="topnav">
+                        <a class="skip" title="skip link" href="#content">Go To Contents</a><span class="hideme">.</span> 
+                        <h2 class="hideme">Service-Navigation</h2>
+                        <ul>
+                            <li><a href="http://www.seqan.de" title="Homepage">Homepage</a></li>
+                            <li><a href="http://www.seqan.de/contact-us/" title="Contact">Contact</a></li>
+                            <li><a href="http://www.seqan.de/legal-notice/" title="Legal notice according to § 5 TMG">Legal Notice</a></li>
+                            <li><a href="http://www.seqan.de/sitemap/" title="Sitemap">Sitemap</a></li>
+                        </ul>
+                    </div>
+                    <!-- #topnav --> 
+                    <div id="services">
+                        <div id="search" class="search">
+                            <div id="search_inner">
+                                <form action="http://www.seqan.de" id="search_form" method="get"> <input class="search_input" id="search_input" locale="de" name="s" title="Enter Search Term" type="text" value=""> <input alt="Start Search" class="search_button" id="search_button" src="http://www.seqan.de/wp-content/themes/fub-theme/images/search_button.gif" title="Start Search" type="image"> </form>
+                            </div>
+                        </div>
+                        <!-- #search --> 
+                        <div id="icons"> <a href="#print" onclick="javascript:self.print();return false;" title="Diese Seite drucken"><img alt="Print (Icon)" id="icon_print" src="http://www.seqan.de/wp-content/themes/fub-theme/images/icon_print.gif" title="print"></a> <a href="http://www.seqan.de/feed/" target="_blank" title="Subscribe to RSS2 Feed"><img alt="RSS (Icon)" id="icon_rss" src="http://www.seqan.de/wp-content/themes/fub-theme/images/icon_rss.gif" title=""></a> </div>
+                        <!-- #icons --> 
+                    </div>
+                    <!-- #services --> 
+                </div>
+                <!-- #header --> <!-- Wrappers for Main Content Row --> 
+                <div id="main" class="page_raster_10_off">
+                    <div class="subcolumns margin_bottom">
+                        <!-- Left Bar --> 
+                        <div class="c20l">
+                            <!-- Navigational Menu Left --> 
+                            <div class="vlist"> </div>
+                            <!-- Left Sidebar --> 
+                        </div>
+                        <!-- Main Content --> 
+                        <div class="c60l" id="main_content">
+                            <div class="post subc subc_default_padding" id="post-2">
+                                <div class="breadcrumbs">
+                                    <p class="hideme">Breadcrumbs</p>
+                                    <ul>
+                                        <li class="first"><a href="http://www.seqan.de">SeqAn</a></li>
+                                        <li class="active">Sub Page</li>
+                                    </ul>
+                                </div>
+                                <h1 class="main_headline" style="margin-top:0;">Sub Page</h1>
+                                <h2>What is SeqAn?</h2>
+                                <p>SeqAn is an open source C++ library of efficient algorithms and data structures for the analysis of sequences with the focus on biological data. Our library applies a unique generic design that guarantees high performance, generality, extensibility, and integration with other libraries. SeqAn is easy to use and simplifies the development of new software tools with a minimal loss of performance.</p>
+                                <h2>Quick Facts</h2>
+                                <ul>
+                                    <li>Programming Language: C++98</li>
+                                    <li>License: BSD/3-clause</li>
+                                    <li>
+                                        Supported Platforms: 
+                                        <ul>
+                                            <li>Windows: Visual C++ 8, 9, 10 and MinGW</li>
+                                            <li>Linux: GNU/g++, LLVM/Clang (3.0+)</li>
+                                            <li>Mac OS X: GNU/g++, LLVM/Clang (3.0+)</li>
+                                        </ul>
+                                    </li>
+                                </ul>
+                                <div class="last_updated"><small class="dimmed"> Last Update 12. September 2012 </small></div>
+                            </div>
+                        </div>
+                    </div>
+                    <!-- #main_content --> <!-- Banner Row --> 
+                    <div id="banner" class="subc box_border_top padding_top padding_left padding_bottom">
+                        <div class="css_classhorizontal_banner">
+                            <div class="textwidget"><a href="http://www.fu-berlin.de"><img src="http://www.seqan.de/wp-content/uploads/2012/02/fu_logo.gif" http:="" www.seqan.de=""></a> </div>
+                        </div>
+                    </div>
+                </div>
+                <!-- id="main" --> <!-- Page Footer --> 
+                <div id="footer">
+                    <div class="subcolumns" id="bottomnav">
+                        <div class="subc padding_left padding_right">
+                            <a href="http://www.seqan.de" title="Home">SeqAn</a> 
+                            <ul>
+                                <li><a href="http://www.seqan.de" title="Homepage">Homepage</a></li>
+                                <li><a href="http://www.seqan.de/contact-us/" title="Contact">Contact</a></li>
+                                <li><a href="http://www.seqan.de/legal-notice/" title="Legal notice according to § 5 TMG">Legal Notice</a></li>
+                                <li><a href="http://www.seqan.de/sitemap/" title="Sitemap">Sitemap</a></li>
+                            </ul>
+                        </div>
+                    </div>
+                </div>
+                <!-- class="page" --> 
+            </div>
+            <!-- class="page_margins" --> 
+        </div>
+    </body>
+</html>
\ No newline at end of file
diff --git a/util/py_lib/seqan/skel.py b/util/py_lib/seqan/skel.py
new file mode 100755
index 0000000..d5a2197
--- /dev/null
+++ b/util/py_lib/seqan/skel.py
@@ -0,0 +1,467 @@
+#!/usr/bin/env python2
+"""SeqAn code generation from templates / skeletons.
+
+This module contains code to help the creation of modules, tests, apps etc.
+It can be called directly or imported and the main() function can be called.
+
+It will perform the following replacements:
+
+  %(AUTHOR)s  will be replaced by the author's name, either given on command
+              line or taken from environment variable SEQAN_AUTHOR.
+
+  %(NAME)s    will be replaced by the name of the generated code.
+  %(TITLE)s   will be replaced by the name of the generated, but centered in
+              74 characters, to be used in the file header comment.
+
+  %(YEAR)d    will be replaced by the current year.
+  %(DATE)s    will be replaced by the current date.
+  %(TIME)s    will be replaced by the current time.
+
+  %(HEADER_GUARD)s  will be replaced by the UPPER_CASE_PATH_H_ to the file.
+
+  %(CMAKE_PROJECT_NAME)s  will be replaced by lower_case_path to the target
+                          directory.
+
+  %(CMAKE_PROJECT_PATH)s  will be replaced by the path to the target directory.
+
+Copyright: (c) 2010, Knut Reinert, FU Berlin
+License:   3-clause BSD (see LICENSE)
+"""
+
+from __future__ import with_statement
+
+__author__ = 'Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>'
+
+import datetime
+import optparse
+import os
+import os.path
+import sys
+import string
+
+import paths
+
+# Add os.path.relpath if it is not already there, so we can use Python 2.5, too.
+# TODO(holtgrew): This could go into a "compatibility" module.
+if not 'relpath' in dir(os.path):
+    import posixpath
+    from posixpath import curdir, sep, pardir, join
+
+    def relpath(path, start=curdir):
+        """Return a relative version of a path"""
+        if not path:
+            raise ValueError("no path specified")
+        start_list = posixpath.abspath(start).split(sep)
+        path_list = posixpath.abspath(path).split(sep)
+        # Work out how much of the filepath is shared by start and path.
+        i = len(posixpath.commonprefix([start_list, path_list]))
+        rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
+        if not rel_list:
+            return curdir
+        return join(*rel_list)
+    os.path.relpath = relpath
+
+# Length of the header comment.
+HEADER_CENTER_WIDTH = 74
+
+# Fallback for author string if neither given on command line or environment
+# Variable SEQAN_AUTHOR.
+DEFAULT_AUTHOR = 'Your Name <your.email at example.net>'
+
+# Program usage string for command line parser.
+USAGE = """
+Usage: %prog [options] repository NAME
+       %prog [options] [module|test|app|demo|header|lheader] NAME LOCATION
+       %prog [options] app_tests LOCATION
+""".strip()
+
+# Program description, used for command line parser.  Will be wrapped by, though.
+DESCRIPTION = """
+The SeqAn code generator.
+
+The first version ("repository") is to be be called to create your new entries
+below the directory sandbox.  The second version is to be called to create new
+library modules, tests, apps, app tests, and demos inside a sandbox.
+""".strip()
+#"""
+#Example:
+#
+#  %prog repository sandbox/john_doe
+#
+#The second version is to be called to create new library modules, tests, apps,
+#and demos inside a sandbox.  Example:
+#
+#  %prog module my_module sandbox/john_doe
+#
+#This command creates a new library module in sandbox/john_doe/include/seqan.
+#It consists of the directory my_module, the files my_module.h and
+#my_module/my_module_base.h.
+#
+#  %prog test my_module sandbox/john_doe
+#
+#This command creates the tests for module "my_module" in sandbox/john_doe.
+#
+#  %prog app my_app sandbox/john_doe
+#
+#This command creates a new application named my_app in sandbox/john_doe/apps.
+#
+#  %prog demo my_demo sandbox/john_doe
+#
+#This command creates a new demo in sandbox/john_doe/demos.
+#""".strip()
+
+def createDirectory(path, dry_run=False):
+    print 'mkdir(%s)' % path
+    print
+    if not dry_run:
+        if not os.path.exists(path):
+            os.mkdir(path)
+
+def configureFile(target_file, source_file, replacements, dry_run, options):
+    print 'Configuring file.'
+    print '  Source:', source_file
+    print '  Target:', target_file
+    print
+    if os.path.exists(target_file) and not options.force:
+        msg = 'Target file already exists.  Move it away and call the script again.'
+        print >>sys.stderr, msg
+        return 1
+
+    with open(source_file, 'rb') as f:
+        contents = f.read()
+    target_contents = contents % replacements
+    if dry_run:
+        print 'The contents of the target file are:'
+        print '-' * 78
+        print target_contents
+        print '-' * 78
+    else:
+        with open(target_file, 'wb') as f:
+            f.write(target_contents)
+    return 0
+
+def _pathToIdentifier(relative_path):
+    result = relative_path.replace('/', '_')
+    result = result.replace('\\', '_')
+    result = result.replace('-', '_')
+    result = result.replace('.', '_')
+    result = result.replace(' ', '_')
+    return result
+
+def buildReplacements(type_, name, location, target_file, options):
+    result = {}
+    result['AUTHOR'] = options.author
+    result['YEAR'] = datetime.date.today().year
+    result['TIME'] = datetime.datetime.now().strftime('%H:%M')
+    result['DATE'] = datetime.date.today().strftime('%Y-%m-%d')
+    result['NAME'] = name
+    result['TITLE'] = name.center(HEADER_CENTER_WIDTH).rstrip()
+    path = os.path.relpath(target_file, paths.repositoryRoot())
+    guard = _pathToIdentifier(path).upper()
+    result['HEADER_GUARD'] = guard + '_'
+    path = os.path.relpath(os.path.dirname(target_file),
+                           paths.repositoryRoot())
+    cmake_project_name = _pathToIdentifier(path)
+    result['CMAKE_PROJECT_NAME'] = cmake_project_name
+    result['CMAKE_PROJECT_PATH'] = path.replace('\\', '\\\\')
+    if type_ == 'repository':
+        result['REPOSITORY_PSEUDO_TARGET_NAME'] = name.replace('/', '_').replace('\\', '_').replace(' ', '_')
+    if type_ == 'app_tests':
+        result['APP_NAME'] = os.path.split(os.path.split(location)[0])[1]
+        result['APP_NAME_U'] = result['APP_NAME'].upper()
+        result['LOCATION'] = os.path.join(os.path.split(os.path.normpath(location))[0])
+    return result
+
+def _checkTargetPaths(target_path, options):
+    """Check that the path does not exist but its parent does."""
+    # Check that the given path does not exist yet.
+    if os.path.exists(target_path) and not options.force:
+        msg = 'The path %s already exists. Move it and call this script again.'
+        print >>sys.stderr, msg % target_path
+        return False
+    # Check that the parent path already exists.
+    if not os.path.exists(os.path.dirname(target_path)):
+        msg = 'The parent of the target path does not exist yet: %s'
+        print >>sys.stderr, msg % os.path.dirname(target_path)
+        print >>sys.stderr, 'Please create it and call this script again.'
+        return False
+    return True
+
+def createModule(name, location, options):
+    include_path = paths.pathToInclude(location)
+    seqan_path = os.path.join(include_path, 'seqan')
+    module_path = os.path.join(seqan_path, name)
+    header_path = os.path.join(seqan_path, '%s.h' % name)
+    print 'Creating module in %s' % module_path
+    if options.create_dirs and not _checkTargetPaths(module_path, options):
+        return 1
+    if options.create_dirs and not _checkTargetPaths(header_path, options):
+        return 1
+    print '  Module path is: %s' % module_path
+    print '  Module header path is: %s' % header_path
+    print ''
+    if options.create_dirs:
+        # Create directory.
+        createDirectory(module_path, options.dry_run)
+    if options.create_programs:
+        # Copy over module header.
+        source_file = paths.pathToTemplate('module_template', 'module.h')
+        target_file = header_path
+        replacements = buildReplacements('module', name, seqan_path, target_file, options)
+        res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+        if res: return res
+        # Copy over header inside module.
+        source_file = paths.pathToTemplate('module_template', 'header.h')
+        target_file = os.path.join(module_path, '%s_base.h' % name)
+        replacements = buildReplacements('module', name, seqan_path, target_file, options)
+        res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+        if res: return res
+    return 0
+
+def createTest(name, location, options):
+    target_path = paths.pathToTest(location, name)
+    print 'Creating test in %s' % target_path
+    if options.create_dirs and not _checkTargetPaths(target_path, options):
+        return 1
+    print '  Target path is: %s' % target_path
+    print ''
+    if options.create_dirs:
+        # Create directory.
+        createDirectory(target_path, options.dry_run)
+    if options.create_programs:
+        # Copy over .cpp file for test and perform replacements.
+        source_file = paths.pathToTemplate('test_template', 'test.cpp')
+        target_file = os.path.join(target_path, 'test_%s.cpp' % name)
+        replacements = buildReplacements('test', name, location, target_file, options)
+        res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+        if res: return res
+        # Copy over .h file for test and perform replacements.
+        source_file = paths.pathToTemplate('test_template', 'test.h')
+        target_file = os.path.join(target_path, 'test_%s.h' % name)
+        replacements = buildReplacements('test', name, location, target_file, options)
+        res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+        if res: return res
+    if options.create_cmakelists:
+        # Copy over CMakeLists.txt file for test and perform replacements.
+        source_file = paths.pathToTemplate('test_template', 'CMakeLists.txt')
+        target_file = os.path.join(target_path, 'CMakeLists.txt')
+        replacements = buildReplacements('test', name, location, target_file, options)
+        res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+        if res: return res
+    return 0
+
+def createApp(name, location, options):
+    target_path = paths.pathToApp(location, name)
+    print 'Creating app in %s' % target_path
+    if options.create_dirs and not _checkTargetPaths(target_path, options):
+        return 1
+    print '  Target path is: %s' % target_path
+    print ''
+    if options.create_programs:
+        # Create directory.
+        createDirectory(target_path, options.dry_run)
+        # Copy over .cpp file for app and perform replacements.
+        source_file = paths.pathToTemplate('app_template', 'app.cpp')
+        target_file = os.path.join(target_path, '%s.cpp' % name)
+        replacements = buildReplacements('app', name, location, target_file, options)
+        res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+        if res: return res
+    if options.create_cmakelists:
+        # Copy over CMakeLists.txt file for app and perform replacements.
+        source_file = paths.pathToTemplate('app_template', 'CMakeLists.txt')
+        target_file = os.path.join(target_path, 'CMakeLists.txt')
+        replacements = buildReplacements('app', name, location, target_file, options)
+        res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+        if res: return res
+    return 0
+
+def createDemo(name, location, options):
+    target_path = paths.pathToDemo(location, name)
+    print 'Creating demo in %s' % target_path
+    if options.create_dirs and not _checkTargetPaths(target_path, options):
+        return 1
+    print '  Target path is: %s' % target_path
+    print ''
+    if options.create_programs:
+        # Copy over .cpp file for app and perform replacements.
+        source_file = paths.pathToTemplate('demo_template', 'demo.cpp')
+        target_file = os.path.join(target_path)
+        replacements = buildReplacements('demo', name, location, target_file, options)
+        res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+        if res: return res
+    return 0
+
+def createHeader(name, location, options):
+    target_path = paths.pathToHeader(location, name)
+    print 'Creating (non-library) header in %s' % target_path
+    if not _checkTargetPaths(target_path, options):
+        return 1
+    print '  Target path is: %s' % target_path
+    print ''
+    # Copy over .h file for app and perform replacements.
+    source_file = paths.pathToTemplate('header_template', 'header.h')
+    target_file = os.path.join(target_path)
+    replacements = buildReplacements('header', name, location, target_file, options)
+    res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+    if res: return res
+    print 'NOTE: Do not forget to add the header to the CMakeLists.txt file!'
+    return 0
+
+def createLibraryHeader(name, location, options):
+    target_path = paths.pathToHeader(location, name)
+    print 'Creating library header in %s' % target_path
+    if not _checkTargetPaths(target_path, options):
+        return 1
+    print '  Target path is: %s' % target_path
+    print ''
+    # Copy over .h file for app and perform replacements.
+    source_file = paths.pathToTemplate('header_template', 'library_header.h')
+    target_file = os.path.join(target_path)
+    replacements = buildReplacements('library_header', name, location, target_file, options)
+    res = configureFile(target_file, source_file, replacements, options.dry_run, options)
+    if res: return res
+    return 0
+
+def createRepository(location, options):
+    print 'Creating module %s' % location
+    target_path = paths.pathToRepository(location)
+    if options.create_dirs and not _checkTargetPaths(target_path, options):
+        return 1
+    print '  Target path is: %s' % target_path
+    print ''
+    if options.create_dirs:
+        # Create directories.
+        createDirectory(target_path, options.dry_run)
+        createDirectory(os.path.join(target_path, 'apps'), options.dry_run)
+        createDirectory(os.path.join(target_path, 'demos'), options.dry_run)
+        createDirectory(os.path.join(target_path, 'include'), options.dry_run)
+        createDirectory(os.path.join(target_path, 'include', 'seqan'), options.dry_run)
+        createDirectory(os.path.join(target_path, 'tests'), options.dry_run)
+    if options.create_cmakelists:
+        # Copy over file ${REPOSITORY}/CMakeLists.txt.
+        target_file = os.path.join(target_path, 'CMakeLists.txt')
+        source_file = paths.pathToTemplate('repository_template', 'CMakeLists.txt')
+        replacements = buildReplacements('repository', location, target_path, target_file, options)
+        configureFile(target_file, source_file, replacements, options.dry_run, options)
+        # Copy over file ${REPOSITORY}/apps/CMakeLists.txt.
+        target_file = os.path.join(target_path, 'apps', 'CMakeLists.txt')
+        source_file = paths.pathToTemplate('repository_template', 'apps_CMakeLists.txt')
+        replacements = buildReplacements('repository', location, target_path, target_file, options)
+        configureFile(target_file, source_file, replacements, options.dry_run, options)
+        # Copy over file ${REPOSITORY}/tests/CMakeLists.txt.
+        target_file = os.path.join(target_path, 'tests', 'CMakeLists.txt')
+        source_file = paths.pathToTemplate('repository_template', 'tests_CMakeLists.txt')
+        replacements = buildReplacements('repository', location, target_path, target_file, options)
+        configureFile(target_file, source_file, replacements, options.dry_run, options)
+        # Copy over file ${REPOSITORY}/demos/CMakeLists.txt.
+        target_file = os.path.join(target_path, 'demos', 'CMakeLists.txt')
+        source_file = paths.pathToTemplate('repository_template', 'demos_CMakeLists.txt')
+        replacements = buildReplacements('repository', location, target_path, target_file, options)
+        configureFile(target_file, source_file, replacements, options.dry_run, options)
+    return 0
+
+def createAppTests(location, options):
+    print 'Creating app tests at %s' % location
+    tests_location = os.path.join(location, 'tests')
+    target_path = paths.pathToRepository(tests_location)
+    if options.create_dirs and not _checkTargetPaths(target_path, options):
+        return 1
+    print '  Target path is: %s' % target_path
+    print ''
+
+    # Create directories.
+    if options.create_dirs:
+        createDirectory(target_path, options.dry_run)
+
+    # Copy over file ${APP}/tests/generate_outputs.sh
+    target_file = os.path.join(target_path, 'generate_outputs.sh')
+    source_file = paths.pathToTemplate('app_tests_template', 'generate_outputs.sh')
+    replacements = buildReplacements('app_tests', location, target_path, target_file, options)
+    configureFile(target_file, source_file, replacements, options.dry_run, options)
+    # Copy over file ${APP}/tests/run_tests.py
+    target_file = os.path.join(target_path, 'run_tests.py')
+    source_file = paths.pathToTemplate('app_tests_template', 'run_tests.py')
+    replacements = buildReplacements('app_tests', location, target_path, target_file, options)
+    configureFile(target_file, source_file, replacements, options.dry_run, options)
+
+    print '=' * 80
+    print 'Do not forget to add the tests in %s:' % os.path.join(location, 'CMakeLists.txt')
+    print ''
+    print '# Add app tests if Python interpreter could be found.'
+    print 'if(PYTHONINTERP_FOUND)'
+    print '  add_test(NAME app_test_%s COMMAND ${PYTHON_EXECUTABLE}' % os.path.split(location)[-1]
+    print '    ${CMAKE_CURRENT_SOURCE_DIR}/tests/run_tests.py ${CMAKE_SOURCE_DIR}'
+    print '    ${CMAKE_BINARY_DIR})'
+    print 'endif(PYTHONINTERP_FOUND)'
+    print '=' * 80
+    
+    return 0
+
+def main():
+    # Parse arguments.
+    parser = optparse.OptionParser(usage=USAGE, description=DESCRIPTION)
+    parser.add_option('-s', '--skel-root', dest='skel_root',
+                      help=('Set path to the directory where the skeletons '
+                            'live in.  Taken from environment variable '
+                            'SEQAN_SKELS if available.'),
+                      default=os.environ.get('SEQAN_SKELS',
+                                             paths.pathToSkeletons()))
+    parser.add_option('-a', '--author', dest='author',
+                      help=('Set author to use.  Should have the format USER '
+                            '<EMAIL>.  Taken from environment variable '
+                            'SEQAN_AUTHOR if it exists.'),
+                      default=os.environ.get('SEQAN_AUTHOR', DEFAULT_AUTHOR))
+    parser.add_option('-d', '--dry-run', dest='dry_run', action='store_true',
+                      help='Do not change anything, just simulate.',
+                      default=False)
+    parser.add_option('-c', '--cmakelists-only', dest='cmakelists_only',
+                      action='store_true',
+                      help='Only create CMakeLists.txt files',
+                      default=False)
+    parser.add_option('--force', dest='force', action='store_true',
+                      help='Overwrite existing files and directories.',
+                      default=False)
+    options, args = parser.parse_args()
+    options.create_cmakelists = True
+    options.create_infos = True
+    options.create_dirs = True
+    options.create_programs = True
+    if options.cmakelists_only:
+        options.create_dirs = False
+        options.create_programs = False
+
+    if not args:
+        parser.print_help(file=sys.stderr)
+        return 1
+    if len(args) < 2:
+        print >>sys.stderr, 'Invalid argument count!'
+        return 1
+    if args[0] not in ['module', 'test', 'app', 'demo', 'repository',
+                       'header', 'lheader', 'app_tests']:
+        print >>sys.stderr, 'Invalid template "%s".' % args[0]
+        return 1
+    if args[0] in['repository', 'app_tests']:
+        if len(args) != 2:
+            print >>sys.stderr, 'Invalid argument count!'
+            return 1
+
+    if args[0] == 'repository':
+        return createRepository(args[1], options)
+    elif args[0] == 'app_tests':
+        return createAppTests(args[1], options)
+    elif len(args) != 3:
+        print >>sys.stderr, 'Invalid argument count!'
+        return 1
+    create_methods = {
+        'module' : createModule,
+        'test': createTest,
+        'app': createApp,
+        'demo': createDemo,
+        'header': createHeader,
+        'lheader': createLibraryHeader,
+        }
+    return create_methods[args[0]](args[1], args[2], options)
+
+if __name__ == '__main__':
+   sys.exit(main())
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/seqan2.git



More information about the debian-med-commit mailing list