[med-svn] [python-burrito] 11/15: New upstream version 0.9.1

Andreas Tille tille at debian.org
Wed Nov 29 09:43:15 UTC 2017


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

tille pushed a commit to branch master
in repository python-burrito.

commit ac7c03881420b3496f1a7a9abaa798f53762eb6f
Author: Andreas Tille <tille at debian.org>
Date:   Wed Nov 29 10:38:46 2017 +0100

    New upstream version 0.9.1
---
 CHANGELOG.md                          |    9 +
 LICENSE                               |   27 +
 MANIFEST.in                           |    8 +
 PKG-INFO                              |   69 ++
 README.rst                            |   44 ++
 burrito.egg-info/PKG-INFO             |   69 ++
 burrito.egg-info/SOURCES.txt          |   16 +
 burrito.egg-info/dependency_links.txt |    1 +
 burrito.egg-info/requires.txt         |    6 +
 burrito.egg-info/top_level.txt        |    1 +
 burrito/__init__.py                   |    9 +
 burrito/parameters.py                 |  492 ++++++++++++
 burrito/tests/__init__.py             |    7 +
 burrito/tests/test_parameters.py      |  659 +++++++++++++++++
 burrito/tests/test_util.py            | 1313 +++++++++++++++++++++++++++++++++
 burrito/util.py                       |  791 ++++++++++++++++++++
 debian/changelog                      |   18 -
 debian/compat                         |    1 -
 debian/control                        |   54 --
 debian/copyright                      |   40 -
 debian/patches/better_error_reporting |   24 -
 debian/patches/series                 |    1 -
 debian/rules                          |   11 -
 debian/source/format                  |    1 -
 debian/watch                          |    2 -
 setup.cfg                             |    5 +
 setup.py                              |   55 ++
 27 files changed, 3581 insertions(+), 152 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..ff702c9
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,9 @@
+# burrito changelog
+
+## Version 0.9.1 (2015-05-22)
+
+* Updated default temporary directory from ``/tmp`` to python's ``tempfile.gettempdir()``. This should address many of the issues with temporary files being written to ``/tmp``, which sometimes doesn't exist, doesn't provide a lot of storage, or is not shared across cluster nodes. It is still possible that individual burrito fillings (i.e., ``CommandLineApplication`` derived classes) can hard code ``/tmp``, so care should be taken when writing those derived classes to avoid that.
+
+## Version 0.9.0 (2014-08-04)
+
+Initial release.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..bdbcede
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2014, burrito development team.
+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 names burrito or biocore 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..c3c8e31
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,8 @@
+include CHANGELOG.md
+include LICENSE
+include README.rst
+
+graft burrito
+
+global-exclude *.pyc
+global-exclude *.pyo
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..9d43f58
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,69 @@
+Metadata-Version: 1.1
+Name: burrito
+Version: 0.9.1
+Summary: Framework for wrapping and controlling command-line applications.
+Home-page: https://github.com/biocore/burrito
+Author: burrito development team
+Author-email: gregcaporaso at gmail.com
+License: BSD
+Description: burrito
+        =======
+        
+        |Build Status| |Coverage Status|
+        
+        burrito, canonically pronounced *boar-eee-toe*, is a Python framework for
+        wrapping and controlling command-line applications.
+        
+        What's with the name?
+        ---------------------
+        
+        This tool allows developers to wrap command-line applications, just as burritos
+        wrap delicious foods. Both hide the potentially unsightly details.
+        
+        Installation
+        ------------
+        
+        To install burrito::
+        
+            pip install burrito
+        
+        Running the tests
+        -----------------
+        
+        To run burrito's unit tests::
+        
+            nosetests
+        
+        The pre-history of burrito
+        --------------------------
+        
+        burrito is derived from the `application controller framework <http://pycogent.org/examples/application_controller_framework.html>`__
+        code, which was originally added to `PyCogent <http://www.pycogent.org>`__ and
+        later moved to `scikit-bio <http://scikit-bio.org>`__. The contributors and/or
+        copyright holders have agreed to make the code they wrote for PyCogent
+        available under the BSD license. The original authors of the application
+        controller framework code in PyCogent are Greg Caporaso
+        (`@gregcaporaso <https://github.com/gregcaporaso>`__), Sandra Smit,
+        Micah Hamady, and Rob Knight (`@rob-knight <https://github.com/rob-knight>`__).
+        
+        .. |Build Status| image:: https://travis-ci.org/biocore/burrito.svg?branch=master
+           :target: https://travis-ci.org/biocore/burrito
+        .. |Coverage Status| image:: https://coveralls.io/repos/biocore/burrito/badge.png
+           :target: https://coveralls.io/r/biocore/burrito
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Operating System :: Unix
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: MacOS :: MacOS X
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..2c88172
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,44 @@
+burrito
+=======
+
+|Build Status| |Coverage Status|
+
+burrito, canonically pronounced *boar-eee-toe*, is a Python framework for
+wrapping and controlling command-line applications.
+
+What's with the name?
+---------------------
+
+This tool allows developers to wrap command-line applications, just as burritos
+wrap delicious foods. Both hide the potentially unsightly details.
+
+Installation
+------------
+
+To install burrito::
+
+    pip install burrito
+
+Running the tests
+-----------------
+
+To run burrito's unit tests::
+
+    nosetests
+
+The pre-history of burrito
+--------------------------
+
+burrito is derived from the `application controller framework <http://pycogent.org/examples/application_controller_framework.html>`__
+code, which was originally added to `PyCogent <http://www.pycogent.org>`__ and
+later moved to `scikit-bio <http://scikit-bio.org>`__. The contributors and/or
+copyright holders have agreed to make the code they wrote for PyCogent
+available under the BSD license. The original authors of the application
+controller framework code in PyCogent are Greg Caporaso
+(`@gregcaporaso <https://github.com/gregcaporaso>`__), Sandra Smit,
+Micah Hamady, and Rob Knight (`@rob-knight <https://github.com/rob-knight>`__).
+
+.. |Build Status| image:: https://travis-ci.org/biocore/burrito.svg?branch=master
+   :target: https://travis-ci.org/biocore/burrito
+.. |Coverage Status| image:: https://coveralls.io/repos/biocore/burrito/badge.png
+   :target: https://coveralls.io/r/biocore/burrito
diff --git a/burrito.egg-info/PKG-INFO b/burrito.egg-info/PKG-INFO
new file mode 100644
index 0000000..9d43f58
--- /dev/null
+++ b/burrito.egg-info/PKG-INFO
@@ -0,0 +1,69 @@
+Metadata-Version: 1.1
+Name: burrito
+Version: 0.9.1
+Summary: Framework for wrapping and controlling command-line applications.
+Home-page: https://github.com/biocore/burrito
+Author: burrito development team
+Author-email: gregcaporaso at gmail.com
+License: BSD
+Description: burrito
+        =======
+        
+        |Build Status| |Coverage Status|
+        
+        burrito, canonically pronounced *boar-eee-toe*, is a Python framework for
+        wrapping and controlling command-line applications.
+        
+        What's with the name?
+        ---------------------
+        
+        This tool allows developers to wrap command-line applications, just as burritos
+        wrap delicious foods. Both hide the potentially unsightly details.
+        
+        Installation
+        ------------
+        
+        To install burrito::
+        
+            pip install burrito
+        
+        Running the tests
+        -----------------
+        
+        To run burrito's unit tests::
+        
+            nosetests
+        
+        The pre-history of burrito
+        --------------------------
+        
+        burrito is derived from the `application controller framework <http://pycogent.org/examples/application_controller_framework.html>`__
+        code, which was originally added to `PyCogent <http://www.pycogent.org>`__ and
+        later moved to `scikit-bio <http://scikit-bio.org>`__. The contributors and/or
+        copyright holders have agreed to make the code they wrote for PyCogent
+        available under the BSD license. The original authors of the application
+        controller framework code in PyCogent are Greg Caporaso
+        (`@gregcaporaso <https://github.com/gregcaporaso>`__), Sandra Smit,
+        Micah Hamady, and Rob Knight (`@rob-knight <https://github.com/rob-knight>`__).
+        
+        .. |Build Status| image:: https://travis-ci.org/biocore/burrito.svg?branch=master
+           :target: https://travis-ci.org/biocore/burrito
+        .. |Coverage Status| image:: https://coveralls.io/repos/biocore/burrito/badge.png
+           :target: https://coveralls.io/r/biocore/burrito
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Operating System :: Unix
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: MacOS :: MacOS X
diff --git a/burrito.egg-info/SOURCES.txt b/burrito.egg-info/SOURCES.txt
new file mode 100644
index 0000000..5413b23
--- /dev/null
+++ b/burrito.egg-info/SOURCES.txt
@@ -0,0 +1,16 @@
+CHANGELOG.md
+LICENSE
+MANIFEST.in
+README.rst
+setup.py
+burrito/__init__.py
+burrito/parameters.py
+burrito/util.py
+burrito.egg-info/PKG-INFO
+burrito.egg-info/SOURCES.txt
+burrito.egg-info/dependency_links.txt
+burrito.egg-info/requires.txt
+burrito.egg-info/top_level.txt
+burrito/tests/__init__.py
+burrito/tests/test_parameters.py
+burrito/tests/test_util.py
\ No newline at end of file
diff --git a/burrito.egg-info/dependency_links.txt b/burrito.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/burrito.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/burrito.egg-info/requires.txt b/burrito.egg-info/requires.txt
new file mode 100644
index 0000000..68c4778
--- /dev/null
+++ b/burrito.egg-info/requires.txt
@@ -0,0 +1,6 @@
+future
+
+[test]
+nose >= 0.10.1
+flake8
+coveralls
\ No newline at end of file
diff --git a/burrito.egg-info/top_level.txt b/burrito.egg-info/top_level.txt
new file mode 100644
index 0000000..49132e0
--- /dev/null
+++ b/burrito.egg-info/top_level.txt
@@ -0,0 +1 @@
+burrito
diff --git a/burrito/__init__.py b/burrito/__init__.py
new file mode 100644
index 0000000..7792d3a
--- /dev/null
+++ b/burrito/__init__.py
@@ -0,0 +1,9 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2014--, burrito development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# ----------------------------------------------------------------------------
+
+__version__ = "0.9.1"
diff --git a/burrito/parameters.py b/burrito/parameters.py
new file mode 100644
index 0000000..60c74b7
--- /dev/null
+++ b/burrito/parameters.py
@@ -0,0 +1,492 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2014--, burrito development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# ----------------------------------------------------------------------------
+
+from copy import deepcopy
+
+from collections import Mapping
+
+
+def is_not_None(x):
+    """Returns True if x is not None"""
+    return x is not None
+
+
+class ParameterError(ValueError):
+
+    """Error raised when field in parameter is bad"""
+    pass
+
+
+class FilePath(str):
+
+    """ Hold paths for proper handling
+
+        Paths in this sense are filenames, directory paths, or filepaths.
+        Some examples include:
+         file.txt
+         ./path/to/file.txt
+         ./path/to/dir/
+         /path/to/file.txt
+         .
+         /
+
+        The purpose of this class is to allow all paths to be handled the
+         same since they sometimes need to be treated differently than
+         simple strings. For example, if a path has a space in it, and it
+         is being passed to system, it needs to be wrapped in quotes. But,
+         you wouldn't want it as a string wrapped in quotes b/c, e.g.,
+         isabs('"/absolute/path"') == False, b/c the first char is a ", not
+         a /.
+
+        * This would make more sense to call Path, but that conflicts with
+            the ResultPath.Path attribute. I'm not sure what to do about this
+            and want to see what others think. Once finalized, a global
+            replace should take care of making the switch.
+
+    """
+    def __new__(cls, path):
+        try:
+            return str.__new__(cls, path.strip('"'))
+        except AttributeError:
+            return str.__new__(cls, '')
+
+    def __str__(self):
+        """ wrap self in quotes, or return the empty string if self == '' """
+        if self == '':
+            return ''
+        return ''.join(['"', self, '"'])
+
+    def __add__(self, other):
+        return FilePath(''.join([self, other]))
+
+
+class Parameter(object):
+
+    """Stores information regarding a parameter to an application.
+
+        An abstract class.
+    """
+
+    def __init__(self, Prefix, Name, Value=None, Delimiter=None,
+                 Quote=None, IsPath=None):
+        """Initialize the Parameter object.
+
+        Prefix: the character(s) preceding the name of the parameter
+            (eg. '-' for a '-a' parameter)
+        Name: the name of the parameter (eg. 'a' for a '-a' parameter)
+        Value: the value of the parameter (eg. '9' in a '-t=9' parameter)
+            The value is also used in subclasses to turn parameters on and off
+        Delimiter: the character separating the identifier and the value,
+            (eg. '=' for a '-t=9' command or ' ' for a '-t 9' parameter)
+        Quote: the character to use when quoting the value (eg. "\"" for
+            a '-l="hello" parameter). At this point asymmetrical quotes
+            are not possible (ie. [4])
+            WARNING: You must escape the quote in most cases.
+        IsPath: boolean indicating whether Value is a file path, and should
+            therefore be cast to a FilePath object
+            WARNING: Don't set Quote='"' and set IsPath=True. This
+            would result in two sets of double quotes being wrapped around
+            the path when it is printed, and the application would most
+            likely fail. We explicitly disallow this with:
+             if self.IsPath and self.Quote == '"': self.Quote = None
+
+        Id: The combination of Prefix and Name is called the identifier (Id)
+            of the parameter. (eg. '-a' for a '-a' parameter, or '-t' for
+            a '-t=9' parameter)
+
+        This is intended to be an abstract class and has no use otherwise.
+        To subclass Parameter, the subclass should implement the
+        following methods:
+            __str__(): returns the parameter as a string when turned on,
+                or as an empty string when turned off
+            on(): turns the parameter on
+            isOn(): return True if a parameter is on, otherwise False
+            off(): turns the parameter off
+            isOff(): return True if a parameter is off, otherwise False
+
+        Whether a parameter is on or off can be specified in different
+        ways in subclasses, your isOn() and isOff() methods should define
+        this.
+
+        Optionally you can overwrite __init__, but you should be sure to
+        either call the superclass init or handle the setting of the
+        self._default attribute (or things will break!)
+
+        """
+        self.Name = Name
+        self.Prefix = Prefix
+        self.Delimiter = Delimiter
+        self.Quote = Quote
+        self.Value = Value
+        self.IsPath = IsPath
+        if self.IsPath and self.Quote == '"':
+            self.Quote = None
+
+    def _get_id(self):
+        """Construct and return the identifier"""
+        return ''.join(map(str,
+                           filter(is_not_None,
+                                  [self.Prefix, self.Name])))
+
+    Id = property(_get_id)
+
+    def __eq__(self, other):
+        """Return True if two parameters are equal"""
+        return (self.IsPath == other.IsPath) and\
+            (self.Name == other.Name) and\
+            (self.Prefix == other.Prefix) and\
+            (self.Delimiter == other.Delimiter) and \
+            (self.Quote == other.Quote) and \
+            (self.Value == other.Value)
+
+    def __ne__(self, other):
+        """Return True if two parameters are not equal to each other"""
+        return not self == other
+
+
+class FlagParameter(Parameter):
+
+    """Stores information regarding a flag parameter to an application"""
+
+    def __init__(self, Prefix, Name, Value=False):
+        """Initialize a FlagParameter object
+
+        Prefix: the character(s) preceding the name of the parameter
+            (eg. '-' for a '-a' parameter)
+        Name: the name of the parameter (eg. 'a' for a '-a' parameter)
+        Value: determines whether the flag is turned on or not;
+            should be True to turn on, or False to turn off,
+            False by default
+
+        Id: The combination of Prefix and Name is called the identifier (Id)
+            of the parameter. (eg. '-a' for a '-a' parameter, or '-t' for
+            a '-t=9' parameter)
+
+        Usage:
+            f = FlagParameter(Prefix='-',Name='a')
+            Parameter f is turned off by default, so it won't be used by
+            the application until turned on.
+
+        or  f = FlagParameter(Prefix='+',Name='d',Value=True)
+            Parameter f is turned on. It will be used by the application.
+        """
+        super(FlagParameter, self).__init__(Name=Name, Prefix=Prefix,
+                                            Value=Value, Delimiter=None,
+                                            Quote=None)
+
+    def __str__(self):
+        """Return the parameter as a string.
+
+        When turned on: string representation of the parameter
+        When turned off: empty string
+        """
+        if self.isOff():
+            return ''
+        else:
+            return ''.join(map(str, [self.Prefix, self.Name]))
+
+    def isOn(self):
+        """Returns True if the FlagParameter is turned on.
+
+        A FlagParameter is turned on if its Value is True or evaluates to True.
+        A FlagParameter is turned off if its Value is False or evaluates
+            to False.
+        """
+        if self.Value:
+            return True
+        return False
+
+    def isOff(self):
+        """Returns True if the parameter is turned off
+
+        A FlagParameter is turned on if its Value is True or evaluates to True.
+        A FlagParameter is turned off if its Value is False or evaluates
+            to False.
+        """
+        return not self.isOn()
+
+    def on(self):
+        """Turns the FlagParameter ON by setting its Value to True"""
+        self.Value = True
+
+    def off(self):
+        """Turns the FlagParameter OFF by setting its Value to False"""
+        self.Value = False
+
+
+class ValuedParameter(Parameter):
+
+    """Stores information regarding a valued parameter to an application"""
+
+    def __init__(self, Prefix, Name, Value=None, Delimiter=None, Quote=None,
+                 IsPath=False):
+        """Initialize a ValuedParameter object.
+
+        Prefix: the character(s) preceding the name of the parameter
+            (eg. '-' for a '-a' parameter)
+        Name: the name of the parameter (eg. 'a' for a '-a' parameter)
+        Value: the value of the parameter (eg. '9' in a '-t=9' parameter)
+        Delimiter: the character separating the identifier and the value,
+            (eg. '=' for a '-t=9' command or ' ' for a '-t 9' parameter)
+        Quote: the character to use when quoting the value (eg. "\"" for
+            a '-l="hello" parameter). At this point asymmetrical quotes
+            are not possible (ie. [4])
+            WARNING: You must escape the quote in most cases.
+        IsPath: boolean indicating whether Value is a file path, and should
+            therefore be cast to a FilePath object
+
+        Id: The combination of Prefix and Name is called the identifier (Id)
+            of the parameter. (eg. '-a' for a '-a' parameter, or '-t' for
+            a '-t=9' parameter)
+        Default: the default value of the parameter; this is defined as
+            what is passed into init for Value and can not be changed
+            after object initialization
+
+        Usage:
+            v = ValuedParameter(Prefix='-',Name='a',Delimiter=' ',Value=3)
+            the parameter is turned on by default (value=3) and will be
+            used by the application as '-a 3'.
+        or  v = ValuedParameter(Prefix='-',Name='d',Delimiter='=')
+            the parameter is turned off by default and won't be used by
+            the application unless turned on with some value.
+        """
+        if IsPath and Value:
+            Value = FilePath(Value)
+        super(ValuedParameter, self).__init__(Name=Name, Prefix=Prefix,
+                                              Value=Value,
+                                              Delimiter=Delimiter,
+                                              Quote=Quote,
+                                              IsPath=IsPath)
+        self._default = Value
+
+    def __str__(self):
+        """Return the parameter as a string
+
+        When turned on: string representation of the parameter
+        When turned off: empty string
+        """
+        if self.isOff():
+            return ''
+        else:
+            parts = [self.Prefix, self.Name, self.Delimiter,
+                     self.Quote, self.Value, self.Quote]
+            return ''.join(map(str, filter(is_not_None, parts)))
+
+    def __eq__(self, other):
+        """Return True if two parameters are equal"""
+        return (self.Name == other.Name) and\
+            (self.Prefix == other.Prefix) and\
+            (self.Delimiter == other.Delimiter) and \
+            (self.Quote == other.Quote) and \
+            (self.Value == other.Value) and\
+            (self._default == other._default)
+
+    def _get_default(self):
+        """Get the default value of the ValuedParameter
+
+        Accessed as a property to avoid the user changing this
+            after initialization.
+        """
+        return self._default
+
+    Default = property(_get_default)
+
+    def reset(self):
+        """Reset Value of the ValuedParameter to the default"""
+        self.Value = self._default
+
+    def isOn(self):
+        """Returns True if the ValuedParameter is turned on
+
+        A ValuedParameter is turned on if its Value is not None.
+        A ValuedParameter is turned off if its Value is None.
+        """
+        if self.Value is not None:
+            return True
+        return False
+
+    def isOff(self):
+        """Returns True if the ValuedParameter is turned off
+
+        A ValuedParameter is turned on if its Value is not None.
+        A ValuedParameter is turned off if its Value is None.
+        """
+        return not self.isOn()
+
+    def on(self, val):
+        """Turns the ValuedParameter ON by setting its Value to val
+
+        An attempt to turn the parameter on with value 'None' will result
+         in an error, since this is the same as turning the parameter off.
+        """
+        if val is None:
+            raise ParameterError("Turning the ValuedParameter on with value "
+                                 "None is the same as turning it off. "
+                                 "Use another value.")
+        elif self.IsPath:
+            self.Value = FilePath(val)
+        else:
+            self.Value = val
+
+    def off(self):
+        """Turns the ValuedParameter OFF by setting its Value to None"""
+        self.Value = None
+
+
+class MixedParameter(ValuedParameter):
+
+    """Stores information regarding a mixed parameter to an application
+
+    A mixed parameter is a mix between a FlagParameter and a ValuedParameter.
+    When its Value is False, the parameter will be turned off.
+    When its Value is set to None, the parameter will behave like a flag.
+    When its Value is set to anything but None or False, it will behave
+        like a ValuedParameter.
+
+    Example: RNAfold [-d[0|1]]
+    You can give either '-d' or '-d0' or '-d1' as input.
+    """
+
+    def __init__(self, Prefix, Name, Value=False, Delimiter=None, Quote=None,
+                 IsPath=False):
+        """Initialize a MixedParameter object
+
+        Prefix: the character(s) preceding the name of the parameter
+        (eg. '-' for a '-a' parameter)
+        Name: the name of the parameter (eg. 'a' for a '-a' parameter)
+        Value: the value of the parameter (eg. '9' in a '-t=9' parameter)
+        Delimiter: the character separating the identifier and the value,
+            (eg. '=' for a '-t=9' command or ' ' for a '-t 9' parameter)
+        Quote: the character to use when quoting the value (eg. "\"" for
+            a '-l="hello" parameter). At this point asymmetrical quotes
+            are not possible (ie. [4])
+            WARNING: You must escape the quote in most cases.
+        IsPath: boolean indicating whether Value is a file path, and should
+            therefore be cast to a FilePath object
+
+        Id: The combination of Prefix and Name is called the identifier (Id)
+            of the parameter. (eg. '-a' for a '-a' parameter, or '-t' for
+            a '-t=9' parameter)
+        Default: the default value of the parameter; this is defined as
+            what is passed into init for Value and can not be changed
+            after object initialization
+
+        Usage:
+            m = MixedParameter(Prefix='-',Name='a',Delimiter=' ',Value=3)
+            the parameter is turned on by default (value=3) and will be
+            used by the application as '-a 3'.
+        or  m = MixedParameter(Prefix='-',Name='d',Delimiter='=',Value=None)
+            the parameter is turned on by default as a flag parameter and
+            will be used by the application as '-d'.
+        or  m = MixedParameter(Prefix='-',Name='d',Delimiter='=')
+            the parameter is turned off by default (Value=False) and won't be
+            used by the application unless turned on with some value.
+        """
+        if IsPath and Value:
+            Value = FilePath(Value)
+        super(MixedParameter, self).__init__(Name=Name, Prefix=Prefix,
+                                             Value=Value, Delimiter=Delimiter,
+                                             Quote=Quote, IsPath=IsPath)
+
+    def __str__(self):
+        """Return the parameter as a string
+
+        When turned on: string representation of the parameter
+        When turned off: empty string
+        """
+        if self.isOff():
+            return ''
+        elif self.Value is None:
+            return ''.join(map(str, [self.Prefix, self.Name]))
+        else:
+            parts = [self.Prefix, self.Name, self.Delimiter,
+                     self.Quote, self.Value, self.Quote]
+            return ''.join(map(str, filter(is_not_None, parts)))
+
+    def isOn(self):
+        """Returns True if the MixedParameter is turned on
+
+        A MixedParameter is turned on if its Value is not False.
+        A MixedParameter is turned off if its Value is False.
+
+        A MixedParameter is used as flag when its Value is None.
+        A MixedParameter is used as ValuedParameter when its Value is
+            anything but None or False.
+        """
+        if self.Value is not False:
+            return True
+        return False
+
+    def isOff(self):
+        """Returns True if the MixedParameter is turned off
+
+        A MixedParameter is turned on if its Value is not False.
+        A MixedParameter is turned off if its Value is False.
+        """
+        return not self.isOn()
+
+    def on(self, val=None):
+        """Turns the MixedParameter ON by setting its Value to val
+
+        An attempt to turn the parameter on with value 'False' will result
+            in an error, since this is the same as turning the parameter off.
+
+        Turning the MixedParameter ON without a value or with value 'None'
+            will let the parameter behave as a flag.
+        """
+        if val is False:
+            raise ParameterError("Turning the ValuedParameter on with value "
+                                 "False is the same as turning it off. Use "
+                                 "another value.")
+        elif self.IsPath:
+            self.Value = FilePath(val)
+        else:
+            self.Value = val
+
+    def off(self):
+        """Turns the MixedParameter OFF by setting its Value to False"""
+        self.Value = False
+
+
+class Parameters(Mapping):
+
+    """Parameters is a dictionary of Parameter objects.
+
+    Parameters provides a mask that lets the user lookup and access parameters
+        by its synonyms.
+    """
+
+    def __init__(self, parameters={}, synonyms={}):
+        """Initialize the Parameters object.
+
+        parameters: a dictionary of Parameter objects keyed by their identifier
+        synonyms: a dictionary of synonyms. Keys are synonyms, values are
+            parameter identifiers.
+        """
+        self._parameters = deepcopy(parameters)
+        self._synonyms = deepcopy(synonyms)
+
+    def __len__(self):
+        return len(self._parameters)
+
+    def __iter__(self):
+        return iter(self._parameters)
+
+    def __getitem__(self, key):
+        try:
+            key = self._synonyms[key]
+        except KeyError:
+            # the key is not a synonym
+            pass
+
+        return self._parameters[key]
+
+    def all_off(self):
+        """Turns all parameters in the dictionary off"""
+        for v in self._parameters.values():
+            v.off()
diff --git a/burrito/tests/__init__.py b/burrito/tests/__init__.py
new file mode 100644
index 0000000..5d6022a
--- /dev/null
+++ b/burrito/tests/__init__.py
@@ -0,0 +1,7 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2014--, burrito development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# ----------------------------------------------------------------------------
diff --git a/burrito/tests/test_parameters.py b/burrito/tests/test_parameters.py
new file mode 100644
index 0000000..28e9b17
--- /dev/null
+++ b/burrito/tests/test_parameters.py
@@ -0,0 +1,659 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2014--, burrito development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# ----------------------------------------------------------------------------
+
+from unittest import TestCase, main
+from burrito.parameters import (FlagParameter, ValuedParameter, MixedParameter,
+                                Parameters, ParameterError, FilePath)
+
+
+class FlagParameterTests(TestCase):
+
+    """ Tests of the FlagParameter class """
+
+    def setUp(self):
+        """Setup some variables for the tests to use """
+        self.p_modify_prefix = [FlagParameter(Name='d', Prefix='-'),
+                                FlagParameter(Name='d', Prefix='--'),
+                                FlagParameter(Name='d', Prefix='')]
+
+        self.p_modify_name = [FlagParameter(Name='d', Prefix='-'),
+                              FlagParameter(Name='D', Prefix='-'),
+                              FlagParameter(Name=4, Prefix='-'),
+                              FlagParameter(Name='abcdef', Prefix='-')]
+
+        self.p_On = [FlagParameter(Name='d', Prefix='-', Value=True),
+                     FlagParameter(Name='d', Prefix='-', Value=5),
+                     FlagParameter(Name='d', Prefix='-', Value=[1]),
+                     FlagParameter(Name='d', Prefix='-', Value='F')]
+
+        self.p_Off = [FlagParameter(Name='d', Prefix='-', Value=False),
+                      FlagParameter(Name='d', Prefix='-', Value=None),
+                      FlagParameter(Name='d', Prefix='-', Value=[]),
+                      FlagParameter(Name='d', Prefix='-', Value=0),
+                      FlagParameter(Name='d', Prefix='-', Value='')]
+
+        self.ID_tests = [FlagParameter(Name='d', Prefix='-'),
+                         FlagParameter(Name='d', Prefix=''),
+                         FlagParameter(Name='', Prefix='-'),
+                         FlagParameter(Name=4, Prefix='-'),
+                         FlagParameter(Name=None, Prefix='-'),
+                         FlagParameter(Name=4, Prefix=None),
+                         FlagParameter(Name='abcdef', Prefix='-')]
+
+    def test_init(self):
+        """FlagParameter: init functions as expected """
+        param = FlagParameter(Name='a', Prefix='-', Value=42)
+        self.assertEqual(param.Name, 'a')
+        self.assertEqual(param.Prefix, '-')
+        self.assertEqual(param.Value, 42)
+        self.assertEqual(param.Delimiter, None)
+        self.assertEqual(param.Quote, None)
+        self.assertEqual(param.Id, '-a')
+
+    def test_init_defaults(self):
+        """FlagParameter: init functions as expected with default values"""
+        p = FlagParameter(Name='a', Prefix='-')
+        self.assertEqual(p.Name, 'a')
+        self.assertEqual(p.Prefix, '-')
+        self.assertEqual(p.Value, False)
+        self.assertEqual(p.Delimiter, None)
+        self.assertEqual(p.Quote, None)
+        self.assertEqual(p.Id, '-a')
+
+    def test_get_id(self):
+        """FlagParameter: _get_id functions as expected """
+
+        expected_results = ['-d', 'd', '-', '-4', '-', '4', '-abcdef']
+
+        for param, exp in zip(self.ID_tests, expected_results):
+            self.assertEqual(param._get_id(), exp)
+
+    def test_eq(self):
+        """FlagParameter: eq functions as expected """
+        p1 = FlagParameter(Name='a', Prefix='-', Value=True)
+        p2 = FlagParameter(Name='a', Prefix='-', Value=True)
+        p3 = FlagParameter(Name='a', Prefix='-')
+        p4 = FlagParameter(Name='i', Prefix='-', Value=True)
+        p5 = FlagParameter(Name='a', Prefix='--', Value=True)
+
+        assert p1 == p2
+        assert not p1 == p3
+        assert not p1 == p4
+        assert not p1 == p5
+        assert not p3 == p4
+        assert not p3 == p5
+        assert not p4 == p5
+
+    def test_ne(self):
+        """FlagParameter: ne functions as expected """
+        p1 = FlagParameter(Name='a', Prefix='-', Value=True)
+        p2 = FlagParameter(Name='a', Prefix='-', Value=True)
+        p3 = FlagParameter(Name='a', Prefix='-')
+        p4 = FlagParameter(Name='i', Prefix='-', Value=True)
+        p5 = FlagParameter(Name='a', Prefix='--', Value=True)
+
+        assert not p1 != p2
+        assert p1 != p3
+        assert p1 != p4
+        assert p1 != p5
+        assert p3 != p4
+        assert p3 != p5
+        assert p4 != p5
+
+    def test_isOn_True(self):
+        """FlagParameter: isOn functions as expected with True Values """
+        for param in self.p_On:
+            assert param.isOn()
+
+    def test_isOn_False(self):
+        """FlagParameter: isOn functions as expected with False Values """
+        for param in self.p_Off:
+            assert not param.isOn()
+
+    def test_isOff_True(self):
+        """FlagParameter: isOff functions as expected with True values """
+        for param in self.p_Off:
+            assert param.isOff()
+
+    def test_isOff_False(self):
+        """FlagParameter: isOff functions as expected with False values """
+        for param in self.p_On:
+            assert not param.isOff()
+
+    def test_on(self):
+        """FlagParameter: on functions as expected """
+        for param in self.p_On + self.p_Off:
+            param.on()
+            assert param.isOn()
+
+    def test_off(self):
+        """FlagParameter: off functions as expected """
+        for param in self.p_On + self.p_Off:
+            param.off()
+            assert param.isOff()
+
+    def test_str_modify_prefix(self):
+        """FlagParameter: str functions as expected with different prefixes """
+
+        expected_results = ['-d', '--d', 'd']
+
+        for param, exp in zip(self.p_modify_prefix, expected_results):
+            param.on()
+            self.assertEqual(str(param), exp)
+
+    def test_str_modify_name(self):
+        """FlagParameter: str functions as expected with different names """
+
+        expected_results = ['-d', '-D', '-4', '-abcdef']
+
+        for param, exp in zip(self.p_modify_name, expected_results):
+            param.on()
+            self.assertEqual(str(param), exp)
+
+
+class ValuedParameterTests(TestCase):
+
+    """ Tests of the ValuedParameter class """
+    constructor = ValuedParameter
+    s = 'Valued'
+
+    def setUp(self):
+        """Setup some variables for the tests to use """
+        self.p_modify_prefix = [self.constructor(Name='d', Prefix='-'),
+                                self.constructor(Name='d', Prefix='--'),
+                                self.constructor(Name='d', Prefix='')]
+
+        self.p_modify_name = [self.constructor(Name='d', Prefix='-'),
+                              self.constructor(Name='D', Prefix='-'),
+                              self.constructor(Name=4, Prefix='-'),
+                              self.constructor(Name='abcdef', Prefix='-')]
+
+        self.p_On = [self.constructor(Name='d', Prefix='-', Value=True),
+                     self.constructor(Name='d', Prefix='-', Value=5),
+                     self.constructor(Name='d', Prefix='-', Value=[1]),
+                     self.constructor(Name='d', Prefix='-', Value=False),
+                     self.constructor(Name='d', Prefix='-', Value='F')]
+
+        self.p_Off = [self.constructor(Name='d', Prefix='-', Value=None)]
+
+        self.p_full = [self.constructor(Name='a', Prefix='-',
+                                        Value=42, Delimiter=' ', Quote='\'')]
+
+        self.p_default = [self.constructor(Name='a', Prefix='-')]
+
+        self.p_modified_prefix = [self.constructor(Name='d', Prefix='-'),
+                                  self.constructor(Name='d', Prefix='--'),
+                                  self.constructor(Name='d', Prefix='')]
+
+        self.p_modified_name = [self.constructor(Name='d', Prefix='-'),
+                                self.constructor(Name='D', Prefix='-'),
+                                self.constructor(Name=4, Prefix='-'),
+                                self.constructor(Name='abcdef', Prefix='-')]
+
+        self.p_modified_delimiter =\
+            [self.constructor(Name='d', Prefix='-', Value=42),
+             self.constructor(Name='d', Prefix='-', Value=42, Delimiter=''),
+             self.constructor(Name='d', Prefix='-', Value=42, Delimiter=' '),
+             self.constructor(Name='d', Prefix='-', Value=42, Delimiter=9),
+             self.constructor(Name='d', Prefix='-', Value=42, Delimiter='=')]
+
+        self.p_modified_value =\
+            [self.constructor(Name='d', Prefix='-', Value=42, Delimiter=' '),
+             self.constructor(
+                 Name='d',
+                 Prefix='-',
+                 Value='pbl',
+                 Delimiter=' '),
+                self.constructor(
+                    Name='d',
+                    Prefix='-',
+                    Value='2-2',
+                    Delimiter=' '),
+                self.constructor(Name='d', Prefix='-', Value='evo/t.txt',
+                                 Delimiter=' '),
+                self.constructor(Name='d', Prefix='-', Value='\'',
+                                 Delimiter=' ')]
+
+        self.p_modified_quote =\
+            [self.constructor(Name='d', Prefix='-', Value=42, Quote=''),
+             self.constructor(Name='d', Prefix='-', Value=42),
+             self.constructor(Name='d', Prefix='-', Value=42, Quote=' '),
+             self.constructor(Name='d', Prefix='-', Value=42, Quote='\''),
+             self.constructor(Name='d', Prefix='-', Value=42, Quote='\"'),
+             self.constructor(Name='d', Prefix='-', Value=42, Quote='x')]
+
+        self.ID_tests = [self.constructor(Name='d', Prefix='-'),
+                         self.constructor(Name='d', Prefix=''),
+                         self.constructor(Name='', Prefix='-'),
+                         self.constructor(Name=4, Prefix='-'),
+                         self.constructor(Name=None, Prefix='-'),
+                         self.constructor(Name=4, Prefix=None),
+                         self.constructor(Name='abcdef', Prefix='-')]
+
+        self.p_modified_is_path =\
+            [self.constructor(Name='d', Prefix='-', Delimiter=' ',
+                              Value='test.txt', IsPath=True),
+             self.constructor(Name='d', Prefix='-', Delimiter=' ',
+                              Value='test.txt', IsPath=False),
+             self.constructor(Name='d', Prefix='-', Delimiter=' ',
+                              Value='test.txt', Quote='"', IsPath=True)]
+
+    def test_init(self):
+        """Parameter: init functions as expected """
+
+        for param in self.p_full:
+            self.assertEqual(param.Name, 'a')
+            self.assertEqual(param.Prefix, '-')
+            self.assertEqual(param.Value, 42)
+            self.assertEqual(param.Delimiter, ' ')
+            self.assertEqual(param.Quote, '\'')
+            self.assertEqual(param.Id, '-a')
+
+    def test_init_defaults(self):
+        """Parameter: init functions as expected with default values"""
+        for p in self.p_default:
+            self.assertEqual(p.Name, 'a')
+            self.assertEqual(p.Prefix, '-')
+            self.assertEqual(p.Value, None)
+            self.assertEqual(p.Delimiter, None)
+            self.assertEqual(p.Quote, None)
+            self.assertEqual(p.Id, '-a')
+
+    def test_get_id(self):
+        """Parameter: _get_id functions as expected """
+
+        expected_results = ['-d', 'd', '-', '-4', '-', '4', '-abcdef']
+
+        for param, exp in zip(self.ID_tests, expected_results):
+            self.assertEqual(param._get_id(), exp)
+
+    def test_eq(self):
+        """Parameter: eq functions as expected """
+        p1 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=')
+        p2 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=')
+        p3 = self.constructor(Name='dsf', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=')
+        p4 = self.constructor(Name='a', Prefix='--', Value=42, Quote='\'',
+                              Delimiter='=')
+        p5 = self.constructor(Name='a', Prefix='-', Value=942, Quote='\'',
+                              Delimiter='=')
+        p6 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\"',
+                              Delimiter='=')
+        p7 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='!!!')
+        p8 = self.constructor(Name='wwwww', Prefix='-------')
+        p9 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=', IsPath=True)
+
+        assert p1 == p2
+        assert not p1 == p3
+        assert not p1 == p4
+        assert not p1 == p5
+        assert not p1 == p6
+        assert not p1 == p7
+        assert not p1 == p8
+        assert not p1 == p9
+        # test default setting
+        p5.Value = 42
+        assert not p1 == p5
+
+    def test_ne(self):
+        """Parameter: ne functions as expected """
+        p1 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=')
+        p2 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=')
+        p3 = self.constructor(Name='dsf', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=')
+        p4 = self.constructor(Name='a', Prefix='--', Value=42, Quote='\'',
+                              Delimiter='=')
+        p5 = self.constructor(Name='a', Prefix='-', Value=942, Quote='\'',
+                              Delimiter='=')
+        p6 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\"',
+                              Delimiter='=')
+        p7 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='!!!')
+        p8 = self.constructor(Name='wwwww', Prefix='-------')
+        p9 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=', IsPath=True)
+
+        assert not p1 != p2
+        assert p1 != p3
+        assert p1 != p4
+        assert p1 != p5
+        assert p1 != p6
+        assert p1 != p7
+        assert p1 != p8
+        assert p1 != p9
+        # test default setting
+        p5.Value = 42
+        assert p1 != p5
+
+    def test_get_default(self):
+        """Parameter: default behaves as expected """
+        p1 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=')
+        self.assertEqual(p1._get_default(), 42)
+        p1.Value = 43
+        self.assertEqual(p1._get_default(), 42)
+
+    def test_get_default_w_IsPath(self):
+        """Parameter: default is a FilePath object when IsPath is set """
+        p = self.constructor(
+            Name='a', Prefix='-', Value='test.txt', Quote='\'',
+            Delimiter='=', IsPath=True)
+        self.assertEqual(p._get_default(), 'test.txt')
+        self.assertEqual(p.Default, 'test.txt')
+        p.Value = 'test2.txt'
+        self.assertEqual(p._get_default(), 'test.txt')
+        self.assertEqual(p.Default, 'test.txt')
+        assert isinstance(p._get_default(), FilePath)
+        assert isinstance(p.Default, FilePath)
+
+    def test_reset(self):
+        """Parameter: reset correctly set Value to _default """
+        p1 = self.constructor(Name='a', Prefix='-', Value=42, Quote='\'',
+                              Delimiter='=')
+        p1.Value = 43
+        self.assertNotEqual(p1.Default, p1.Value)
+        p1.reset()
+        self.assertEqual(p1.Default, p1.Value)
+
+    def test_isOn_True(self):
+        """Parameter: isOn functions as expected with True Values """
+        for param in self.p_On:
+            assert param.isOn()
+
+    def test_isOn_False(self):
+        """Parameter: isOn functions as expected with False Values """
+        for param in self.p_Off:
+            assert not param.isOn()
+
+    def test_isOff_True(self):
+        """Parameter: isOff functions as expected with True values """
+        for param in self.p_Off:
+            assert param.isOff()
+
+    def test_isOff_False(self):
+        """Parameter: isOff functions as expected with False values """
+        for param in self.p_On:
+            assert not param.isOff()
+
+    def test_on(self):
+        """Parameter: on functions as expected """
+        for param in self.p_On + self.p_Off:
+            param.on('a')
+            assert param.isOn()
+        p = self.p_On[0]
+        self.assertRaises(ParameterError, p.on, None)
+
+    def test_off(self):
+        """Parameter: off functions as expected """
+        for param in self.p_On + self.p_Off:
+            param.off()
+            assert param.isOff()
+
+    def test_str_off(self):
+        """Parameter: str() prints empty string when off """
+        for p in self.p_Off:
+            self.assertEqual(str(p), '')
+
+    def test_str_modify_prefix(self):
+        """Parameter: str functions as expected with different prefixes """
+
+        expected_results = ['-d', '--d', 'd']
+
+        for param, exp in zip(self.p_modified_prefix, expected_results):
+            param.on('')
+            self.assertEqual(str(param), exp)
+
+    def test_str_modify_name(self):
+        """Parameter: str functions as expected with different names """
+
+        expected_results = ['-d', '-D', '-4', '-abcdef']
+
+        for param, exp in zip(self.p_modified_name, expected_results):
+            param.on('')
+            self.assertEqual(str(param), exp)
+
+    def test_str_modify_delimiter(self):
+        """Parameter: str functions as expected with different delimiter """
+
+        expected_results = ['-d42', '-d42', '-d 42', '-d942', '-d=42']
+
+        for param, exp in zip(self.p_modified_delimiter, expected_results):
+            self.assertEqual(str(param), exp)
+
+    def test_str_modify_values(self):
+        """Parameter: str functions as expected with different values """
+
+        expected_results = ['-d 42',
+                            '-d pbl', '-d 2-2', '-d evo/t.txt', '-d \'']
+
+        for param, exp in zip(self.p_modified_value, expected_results):
+            self.assertEqual(str(param), exp)
+
+    def test_str_modify_quotes(self):
+        """Parameter: str functions as expected with different quotes """
+
+        expected_results = ['-d42', '-d42', '-d 42 ', '-d\'42\'',
+                            '-d\"42\"', '-dx42x']
+
+        for param, exp in zip(self.p_modified_quote, expected_results):
+            self.assertEqual(str(param), exp)
+
+    def test_str_modify_is_path(self):
+        """Parameter: str functions as expected with different IsPath """
+
+        expected_results = ['-d "test.txt"', '-d test.txt', '-d "test.txt"']
+
+        for param, exp in zip(self.p_modified_is_path, expected_results):
+            self.assertEqual(str(param), exp)
+
+    def test_str_full(self):
+        """Parameter: str functions as expected with all values non-default """
+        for p in self.p_full:
+            self.assertEqual(str(p), '-a \'42\'')
+
+
+class MixedParameterTests(ValuedParameterTests):
+
+    """ Tests of the MixedParameter class """
+
+    constructor = MixedParameter
+
+    def setUp(self):
+        """Setup some variables for the tests to use """
+        super(MixedParameterTests, self).setUp()
+        self.p_On = [self.constructor(Name='d', Prefix='-', Value=True),
+                     self.constructor(Name='d', Prefix='-', Value=5),
+                     self.constructor(Name='d', Prefix='-', Value=[1]),
+                     self.constructor(Name='d', Prefix='-', Value=None),
+                     self.constructor(Name='d', Prefix='-', Value='F')]
+
+        self.p_Off = [self.constructor(Name='d', Prefix='-', Value=False)]
+
+        # This is different from the superclass variable b/c we need to make
+        # sure that specifying IsPath with Value=None functions as expected
+        self.p_modified_is_path =\
+            [self.constructor(Name='d', Prefix='-', Delimiter=' ',
+                              Value='test.txt', IsPath=True),
+             self.constructor(Name='d', Prefix='-', Delimiter=' ',
+                              Value='test.txt', Quote='"', IsPath=True),
+             self.constructor(Name='d', Prefix='-', Delimiter=' ',
+                              Value='test.txt', IsPath=False),
+             self.constructor(Name='d', Prefix='-', Delimiter=' ',
+                              Value=None, IsPath=True),
+             self.constructor(Name='d', Prefix='-', Delimiter=' ',
+                              Value=None, IsPath=False)]
+
+    def test_on(self):
+        """Parameter: on functions as expected """
+        for param in self.p_On + self.p_Off:
+            param.on('a')
+            assert param.isOn()
+        p = self.p_On[0]
+        self.assertRaises(ParameterError, p.on, False)
+
+    def test_init_defaults(self):
+        """MixedParameter: init functions as expected with default values"""
+        for p in self.p_default:
+            self.assertEqual(p.Name, 'a')
+            self.assertEqual(p.Prefix, '-')
+            self.assertEqual(p.Value, False)
+            self.assertEqual(p.Delimiter, None)
+            self.assertEqual(p.Quote, None)
+            self.assertEqual(p.Id, '-a')
+            self.assertEqual(p.IsPath, False)
+
+    def test_str_all_modes(self):
+        """MixedParameter: str() functions in various modes """
+        p = MixedParameter(Prefix='-', Name='d', Delimiter='=', Quote=']')
+        self.assertEqual(str(p), '')
+        p.on()
+        self.assertEqual(str(p), '-d')
+        p.on('a')
+        self.assertEqual(str(p), '-d=]a]')
+
+    def test_str_modify_is_path(self):
+        """MixedParameter: str functions as expected with different IsPath """
+
+        # This is different from the superclass test b/c we need to make
+        # sure that specifying IsPath with Value=None functions as expected
+        expected_results = ['-d "test.txt"', '-d "test.txt"',
+                            '-d test.txt', '-d', '-d']
+
+        for param, exp in zip(self.p_modified_is_path, expected_results):
+            self.assertEqual(str(param), exp)
+
+
+class ParametersTests(TestCase):
+
+    """Tests of the Parameters class"""
+
+    def setUp(self):
+        self.fp = FlagParameter(Prefix='-', Name='d')
+        self.vp = ValuedParameter(Name='p', Prefix='-', Value=[1])
+        self.mp = MixedParameter(Prefix='--', Name='k', Delimiter=' ')
+        self.all_params = {self.fp.Id: self.fp, self.vp.Id: self.vp,
+                           self.mp.Id: self.mp}
+        self.p1 = Parameters()
+        self.p2 = Parameters(self.all_params)
+        self._synonyms = {'Pino': '-p', 'K': 'k'}
+        self.p3 = Parameters(self.all_params, self._synonyms)
+
+    def test_init(self):
+        """Parameters: init functions as expected"""
+        self.assertEqual(self.p1, {})
+        self.assertEqual(self.p2, self.all_params)
+        self.assertEqual(self.p3, self.all_params)
+
+    def test_lookup(self):
+        """Parameters: test ability to lookup """
+        self.assertEqual(self.p2['-p'], self.vp)
+        self.assertEqual(self.p3['Pino'], self.vp)
+
+    def test_immutability(self):
+        """Parameters: attempt to modify object raises error """
+        try:
+            self.p2['-p'] = 42
+        except TypeError:
+            pass
+        else:
+            raise AttributeError("Parameters shouldn't support assignment.")
+
+        try:
+            del self.p2['-p']
+        except TypeError:
+            pass
+        else:
+            raise AttributeError("Parameters shouldn't support deletion.")
+
+    def test_all_off(self):
+        """Parameters: all_off() should turn all parameters off"""
+        p = self.p2
+        # turn everything on
+        for v in p.values():
+            try:
+                v.on(3)
+            except TypeError:
+                v.on()
+            self.assertTrue(v.isOn())
+
+        # turn everything off
+        p.all_off()
+        for v in p.values():
+            self.assertTrue(v.isOff())
+
+
+class FilePathTests(TestCase):
+
+    """ Tests of the FilePath class """
+
+    def setUp(self):
+        """ Initialize variables to be used by tests """
+        self.filename = 'filename.txt'
+        self.relative_dir_path = 'a/relative/path/'
+        self.relative_dir_path_no_trailing_slash = 'a/relative/path'
+        self.relative_file_path = 'a/relative/filepath.txt'
+        self.absolute_dir_path = '/absolute/path/'
+        self.absolute_file_path = '/absolute/filepath.txt'
+        self.all_paths = [self.filename, self.relative_dir_path,
+                          self.relative_file_path, self.absolute_dir_path,
+                          self.absolute_file_path]
+
+    def test_init(self):
+        """FilePath: initialization returns w/o error """
+        for p in self.all_paths:
+            self.assertEqual(FilePath(p), p)
+        self.assertEqual(FilePath(''), '')
+
+    def test_str(self):
+        """FilePath: str wraps path in quotes """
+        # Do one explicit test (for sanity), then automatically run
+        # through the examples
+        self.assertEqual(str(FilePath(self.filename)), '"filename.txt"')
+        for p in self.all_paths:
+            self.assertEqual(str(FilePath(p)), '"' + p + '"')
+
+    def test_str_path_is_None(self):
+        """FilePath: str return empty string when path is None """
+        self.assertEqual(str(FilePath(None)), '')
+
+    def test_add(self):
+        """FilePath: add (or joining of paths) functions as expected """
+        actual = FilePath(self.relative_dir_path) + FilePath(self.filename)
+        expected = FilePath('a/relative/path/filename.txt')
+        self.assertEqual(actual, expected)
+        # result is a FilePath
+        assert isinstance(actual, FilePath)
+        # appending a string to a FilePath results in a FilePath
+        actual = FilePath(self.relative_dir_path) + 'filename.txt'
+        expected = FilePath('a/relative/path/filename.txt')
+        self.assertEqual(actual, expected)
+        # result is a FilePath
+        assert isinstance(actual, FilePath)
+
+    def test_FilePath_identity_preserved(self):
+        """FilePath: trivial actions on FilePaths yeild original FilePath
+        """
+        p = FilePath(self.filename)
+        # Creating FilePath from FilePath results in FilePath
+        # equal to original
+        self.assertEqual(FilePath(p), p)
+        for p in self.all_paths:
+            self.assertEqual(FilePath(p), p)
+        # Appending an empty FilePath to a FilePath results in FilePath
+        # equal to original
+        self.assertEqual(p + FilePath(''), p)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/burrito/tests/test_util.py b/burrito/tests/test_util.py
new file mode 100644
index 0000000..d222e6e
--- /dev/null
+++ b/burrito/tests/test_util.py
@@ -0,0 +1,1313 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2014--, burrito development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# ----------------------------------------------------------------------------
+
+from tempfile import gettempdir
+from os import remove, system, rmdir, getcwd, walk
+from os.path import exists
+from copy import deepcopy
+
+from burrito.parameters import (FilePath, ValuedParameter, FlagParameter,
+                                MixedParameter)
+from unittest import TestCase
+from burrito.util import (CommandLineApplication, ResultPath, ApplicationError,
+                          ParameterIterBase, ParameterCombinations,
+                          cmdline_generator, ApplicationNotFoundError,
+                          get_tmp_filename, guess_input_handler, which)
+
+
+class ParameterCombinationsTests(TestCase):
+
+    def setUp(self):
+        """Setup for ParameterCombinations tests"""
+        self.mock_app = ParameterCombinationsApp
+        self.params = {'-flag1': True,
+                       '--value1': list(range(0, 5)),
+                       '-delim': list(range(0, 2)),
+                       '-mix1': [None] + list(range(0, 3))}
+        self.always_on = ['--value1']
+        self.param_iter = ParameterCombinations(self.mock_app, self.params,
+                                                self.always_on)
+
+    def test_init_generator(self):
+        """Tests generator capabilities"""
+        all_params = list(self.param_iter)
+        self.assertEqual(len(all_params), 150)
+        params = {'-flag1': True,
+                  '--value1': 1,
+                  '-delim': ['choice1', 'choice2']}
+        always_on = ['-flag1', '-delim']
+        param_iter = ParameterCombinations(self.mock_app, params, always_on)
+
+        exp = [deepcopy(self.mock_app._parameters),
+               deepcopy(self.mock_app._parameters),
+               deepcopy(self.mock_app._parameters),
+               deepcopy(self.mock_app._parameters)]
+
+        # default is on in all these cases
+        exp[0]['-flag1'].on()
+        exp[0]['--value1'].on(1)
+        exp[0]['-delim'].on('choice1')
+
+        exp[1]['-flag1'].on()
+        exp[1]['--value1'].on(1)
+        exp[1]['-delim'].on('choice2')
+
+        exp[2]['-flag1'].on()
+        exp[2]['--value1'].off()
+        exp[2]['-delim'].on('choice1')
+
+        exp[3]['-flag1'].on()
+        exp[3]['--value1'].off()
+        exp[3]['-delim'].on('choice2')
+
+        obs = list(param_iter)
+        self.assertEqual(obs, exp)
+
+    def test_reset(self):
+        """Resets the iterator"""
+        first = list(self.param_iter)
+        self.assertRaises(StopIteration, lambda: next(self.param_iter))
+        self.param_iter.reset()
+        second = list(self.param_iter)
+        self.assertEqual(first, second)
+
+
+class ParameterIterBaseTests(TestCase):
+
+    def setUp(self):
+        """Setup for ParameterIterBase tests"""
+        self.mock_app = ParameterCombinationsApp
+        self.params = {'-flag1': True,
+                       '--value1': list(range(0, 5)),
+                       '-delim': list(range(0, 2)),
+                       '-mix1': [None] + list(range(0, 3))}
+        self.always_on = ['--value1']
+        self.param_base = ParameterIterBase(self.mock_app, self.params,
+                                            self.always_on)
+
+    def test_init(self):
+        """Test constructor"""
+        exp_params = {'-flag1': [True, False],
+                      '--value1': list(range(0, 5)),
+                      '-delim': list(range(0, 2)) + [False],
+                      '-mix1': [None, 0, 1, 2] + [False]}
+
+        self.assertEqual(exp_params,
+                         dict(zip(self.param_base._keys,
+                                  self.param_base._values)))
+
+        self.params['asdasda'] = 5
+        self.assertRaises(ValueError, ParameterIterBase, self.mock_app,
+                          self.params, self.always_on)
+
+        self.params.pop('asdasda')
+        self.always_on.append('asdasd')
+        self.assertRaises(ValueError, ParameterIterBase, self.mock_app,
+                          self.params, self.always_on)
+
+    def test_make_app_params(self):
+        """Returns app parameters with expected values set"""
+        values = [0, 0, True, None]
+        exp = deepcopy(self.mock_app._parameters)
+        exp['-flag1'].on()
+        exp['--value1'].on(0)
+        exp['-delim'].on(0)
+        exp['-mix1'].on(None)
+        obs = self.param_base._make_app_params(values)
+        self.assertEqual(obs, exp)
+
+        state = [4, False, False, False]
+        exp = deepcopy(self.mock_app._parameters)
+        exp['-flag1'].off()
+        exp['--value1'].on(4)
+        exp['-delim'].off()
+        exp['-mix1'].off()
+        obs = self.param_base._make_app_params(state)
+        self.assertEqual(obs, exp)
+
+
+class CommandLineGeneratorTests(TestCase):
+
+    def setUp(self):
+        self.abs_path_to_bin = '/bin/path'
+        self.abs_path_to_cmd = '/cmd/path'
+        self.abs_path_to_input = '/input/path'
+        self.abs_path_to_output = '/output/path'
+        self.abs_path_to_stdout = '/stdout/path'
+        self.abs_path_to_stderr = '/stderr/path'
+        self.app = ParameterCombinationsApp
+
+        params = {'-flag1': True,
+                  '-delim': ['choice1', 'choice2']}
+        always_on = ['-delim']
+        self.mock_app = ParameterCombinationsApp
+        self.param_iter = ParameterCombinations(
+            self.mock_app,
+            params,
+            always_on)
+
+    def test_cmdline_generator_easy(self):
+        """Returns parameter combinations commandlines"""
+        cmdgen = cmdline_generator(self.param_iter,
+                                   PathToBin=self.abs_path_to_bin,
+                                   PathToCmd=self.abs_path_to_cmd,
+                                   PathsToInputs=self.abs_path_to_input,
+                                   PathToOutput=self.abs_path_to_output,
+                                   PathToStdout=self.abs_path_to_stdout,
+                                   PathToStderr=self.abs_path_to_stderr,
+                                   UniqueOutputs=False,
+                                   InputParam='-input',
+                                   OutputParam='-output')
+        bin = self.abs_path_to_bin
+        cmd = self.abs_path_to_cmd
+        inputfile = self.abs_path_to_input
+        outputfile = self.abs_path_to_output
+        stdout = self.abs_path_to_stdout
+        stderr = self.abs_path_to_stderr
+
+        exp = [' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                         '-flag1',
+                         '-input="%s"' % inputfile,
+                         '-output="%s"' % outputfile,
+                         '> "%s"' % stdout, '2> "%s"' % stderr])]
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                             '-input="%s"' % inputfile,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                             '-flag1', '-input="%s"' % inputfile,
+                             '-output="%s"' % outputfile, '> "%s"' % stdout,
+                             '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                             '-input="%s"' % inputfile,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+
+        cmdlines = list(cmdgen)
+        self.assertEqual(cmdlines, exp)
+
+    def test_cmdline_generator_hard(self):
+        """Returns parameter combinations commandlines. Test stdin/stdout"""
+        cmdgen = cmdline_generator(self.param_iter,
+                                   PathToBin=self.abs_path_to_bin,
+                                   PathToCmd=self.abs_path_to_cmd,
+                                   PathsToInputs=self.abs_path_to_input,
+                                   PathToOutput=self.abs_path_to_output,
+                                   PathToStdout=self.abs_path_to_stdout,
+                                   PathToStderr=self.abs_path_to_stderr,
+                                   UniqueOutputs=True,
+                                   InputParam=None,
+                                   OutputParam=None)
+        bin = self.abs_path_to_bin
+        cmd = self.abs_path_to_cmd
+        inputfile = self.abs_path_to_input
+        outputfile = self.abs_path_to_output
+        stderr = self.abs_path_to_stderr
+
+        # the extra '' is intentionally added. When stdout is used for actual
+        # output, the stdout_ param gets set to '' which results in an extra
+        # space being generated on the cmdline. this should be benign
+        # across operating systems
+        exp = [' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                         '-flag1',
+                         '< "%s"' % inputfile, '> "%s"0' % outputfile, '',
+                         '2> "%s"' % stderr])]
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                            '< "%s"' % inputfile, '> "%s"1' % outputfile, '',
+                             '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                            '-flag1', '< "%s"' % inputfile,
+                             '> "%s"2' % outputfile, '', '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                            '< "%s"' % inputfile, '> "%s"3' % outputfile, '',
+                             '2> "%s"' % stderr]))
+
+        cmdlines = list(cmdgen)
+        self.assertEqual(cmdlines, exp)
+
+    def test_cmdline_generator_stdout_stderr_off(self):
+        """Returns cmdlines with stdout and stderr disabled"""
+        cmdgen = cmdline_generator(self.param_iter,
+                                   PathToBin=self.abs_path_to_bin,
+                                   PathToCmd=self.abs_path_to_cmd,
+                                   PathsToInputs=self.abs_path_to_input,
+                                   PathToOutput=self.abs_path_to_output,
+                                   PathToStdout=None,
+                                   PathToStderr=None,
+                                   UniqueOutputs=False,
+                                   InputParam='-input',
+                                   OutputParam='-output')
+        bin = self.abs_path_to_bin
+        cmd = self.abs_path_to_cmd
+        inputfile = self.abs_path_to_input
+        outputfile = self.abs_path_to_output
+
+        exp = [' '.join([bin, cmd, '-default=42', '-delimaaachoice1', '-flag1',
+                        '-input="%s"' % inputfile, '-output="%s"' % outputfile,
+                         '', ''])]
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                             '-input="%s"' % inputfile,
+                             '-output="%s"' % outputfile,
+                             '', '']))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                            '-flag1', '-input="%s"' % inputfile,
+                             '-output="%s"' % outputfile, '', '']))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                             '-input="%s"' % inputfile,
+                             '-output="%s"' % outputfile,
+                             '', '']))
+
+        cmdlines = list(cmdgen)
+        self.assertEqual(cmdlines, exp)
+
+    def test_cmdline_generator_multiple_inputs(self):
+        """Tests the cmdline_generator for multiple input support"""
+        paths_to_inputs = ['/some/dir/a', '/some/dir/b']
+        cmdgen = cmdline_generator(self.param_iter,
+                                   PathToBin=self.abs_path_to_bin,
+                                   PathToCmd=self.abs_path_to_cmd,
+                                   PathsToInputs=paths_to_inputs,
+                                   PathToOutput=self.abs_path_to_output,
+                                   PathToStdout=self.abs_path_to_stdout,
+                                   PathToStderr=self.abs_path_to_stderr,
+                                   UniqueOutputs=False,
+                                   InputParam='-input',
+                                   OutputParam='-output')
+        bin = self.abs_path_to_bin
+        cmd = self.abs_path_to_cmd
+        inputfile1 = paths_to_inputs[0]
+        inputfile2 = paths_to_inputs[1]
+        outputfile = self.abs_path_to_output
+        stdout = self.abs_path_to_stdout
+        stderr = self.abs_path_to_stderr
+
+        exp = [' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                         '-flag1', '-input="%s"' % inputfile1,
+                         '-output="%s"' % outputfile,
+                         '> "%s"' % stdout, '2> "%s"' % stderr])]
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                   '-flag1', '-input="%s"' % inputfile2,
+                             '-output="%s"' % outputfile, '> "%s"' % stdout,
+                             '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                             '-input="%s"' % inputfile1,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                             '-input="%s"' % inputfile2,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                            '-flag1', '-input="%s"' % inputfile1,
+                             '-output="%s"' % outputfile, '> "%s"' % stdout,
+                             '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                            '-flag1', '-input="%s"' % inputfile2,
+                             '-output="%s"' % outputfile, '> "%s"' % stdout,
+                             '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                             '-input="%s"' % inputfile1,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                             '-input="%s"' % inputfile2,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+
+        cmdlines = list(cmdgen)
+        self.assertEqual(cmdlines, exp)
+
+    def test_cmdline_generator_multiple_input_stdin(self):
+        """Tests cmdline_generator for multiple inputs over stdin"""
+        paths_to_inputs = ['/some/dir/a', '/some/dir/b']
+        cmdgen = cmdline_generator(self.param_iter,
+                                   PathToBin=self.abs_path_to_bin,
+                                   PathToCmd=self.abs_path_to_cmd,
+                                   PathsToInputs=paths_to_inputs,
+                                   PathToOutput=self.abs_path_to_output,
+                                   PathToStdout=self.abs_path_to_stdout,
+                                   PathToStderr=self.abs_path_to_stderr,
+                                   UniqueOutputs=False,
+                                   InputParam=None,
+                                   OutputParam='-output')
+        bin = self.abs_path_to_bin
+        cmd = self.abs_path_to_cmd
+        inputfile1 = paths_to_inputs[0]
+        inputfile2 = paths_to_inputs[1]
+        outputfile = self.abs_path_to_output
+        stdout = self.abs_path_to_stdout
+        stderr = self.abs_path_to_stderr
+
+        exp = [' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                         '-flag1', '< "%s"' % inputfile1,
+                         '-output="%s"' % outputfile,
+                         '> "%s"' % stdout, '2> "%s"' % stderr])]
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                   '-flag1', '< "%s"' % inputfile2,
+                             '-output="%s"' % outputfile, '> "%s"' % stdout,
+                             '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                             '< "%s"' % inputfile1,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice1',
+                             '< "%s"' % inputfile2,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                            '-flag1', '< "%s"' % inputfile1,
+                             '-output="%s"' % outputfile, '> "%s"' % stdout,
+                             '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                            '-flag1', '< "%s"' % inputfile2,
+                             '-output="%s"' % outputfile, '> "%s"' % stdout,
+                             '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                             '< "%s"' % inputfile1,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+        exp.append(' '.join([bin, cmd, '-default=42', '-delimaaachoice2',
+                             '< "%s"' % inputfile2,
+                             '-output="%s"' % outputfile,
+                             '> "%s"' % stdout, '2> "%s"' % stderr]))
+
+        cmdlines = list(cmdgen)
+        self.assertEqual(cmdlines, exp)
+
+    def test_cmdline_generator_missing_input_output_paths(self):
+        # missing input
+        with self.assertRaises(ValueError):
+            list(cmdline_generator(None, PathsToInputs=None))
+        with self.assertRaises(ValueError):
+            list(cmdline_generator(None, PathsToInputs=''))
+        with self.assertRaises(ValueError):
+            list(cmdline_generator(None, PathsToInputs=[]))
+
+        # missing output
+        with self.assertRaises(ValueError):
+            list(cmdline_generator(None, PathsToInputs=['/foo/bar/baz'],
+                                   PathToOutput=None))
+        with self.assertRaises(ValueError):
+            list(cmdline_generator(None, PathsToInputs=['/foo/bar/baz'],
+                                   PathToOutput=''))
+
+
+class CommandLineApplicationTests(TestCase):
+
+    """Tests for the CommandLineApplication class"""
+
+    def setUp(self):
+        """setUp for all CommandLineApplication tests"""
+
+        f = open('/tmp/CLAppTester.py', 'w')
+        f.write(script)
+        f.close()
+        system('chmod 777 /tmp/CLAppTester.py')
+
+        # create a copy of the script with a space in the name
+        f = open('/tmp/CLApp Tester.py', 'w')
+        f.write(script)
+        f.close()
+        system('chmod 777 "/tmp/CLApp Tester.py"')
+
+        self.app_no_params = CLAppTester()
+        self.app_no_params_no_stderr = CLAppTester(SuppressStderr=True)
+        self.app_params = CLAppTester({'-F': 'p_file.txt'})
+        self.app_params_space_in_command =\
+            CLAppTester_space_in_command({'-F': 'p_file.txt'})
+        self.app_params_no_stderr = CLAppTester({'-F': 'p_file.txt'},
+                                                SuppressStderr=True)
+        self.app_params_no_stdout = CLAppTester({'-F': 'p_file.txt'},
+                                                SuppressStdout=True)
+        self.app_params_input_as_file = \
+            CLAppTester({'-F': 'p_file.txt'},
+                        InputHandler='_input_as_lines')
+        self.app_params_WorkingDir = CLAppTester({'-F': 'p_file.txt'},
+                                                 WorkingDir='/tmp/test')
+        self.app_params_WorkingDir_w_space = \
+            CLAppTester({'-F': 'p_file.txt'},
+                        WorkingDir='/tmp/test space')
+        self.app_params_TmpDir = CLAppTester({'-F': 'p_file.txt'},
+                                             TmpDir='/tmp/tmp2')
+        self.app_params_TmpDir_w_space = \
+            CLAppTester({'-F': 'p_file.txt'},
+                        TmpDir='/tmp/tmp space')
+        self.data = 42
+
+    def test_base_command(self):
+        """CLAppTester: BaseCommand correctly composed """
+        # No parameters on
+        app = CLAppTester()
+        self.assertEqual(app.BaseCommand, 'cd "/tmp/"; /tmp/CLAppTester.py')
+        # ValuedParameter on/off
+        app.Parameters['-F'].on('junk.txt')
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; /tmp/CLAppTester.py -F "junk.txt"')
+        app.Parameters['-F'].off()
+        self.assertEqual(app.BaseCommand, 'cd "/tmp/"; /tmp/CLAppTester.py')
+        # ValuedParameter accessed by synonym turned on/off
+        app.Parameters['File'].on('junk.txt')
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; /tmp/CLAppTester.py -F "junk.txt"')
+        app.Parameters['File'].off()
+        self.assertEqual(app.BaseCommand, 'cd "/tmp/"; /tmp/CLAppTester.py')
+        # Try multiple parameters, must check for a few different options
+        # because parameters are printed in arbitrary order
+        app.Parameters['-F'].on('junk.txt')
+        app.Parameters['--duh'].on()
+        self.assertTrue(
+            app.BaseCommand ==
+            'cd "/tmp/"; /tmp/CLAppTester.py -F "junk.txt" --duh' or
+            app.BaseCommand ==
+            'cd "/tmp/"; /tmp/CLAppTester.py --duh -F "junk.txt"')
+        # Space in _command
+        app = CLAppTester_space_in_command()
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; "/tmp/CLApp Tester.py"')
+
+    def test_getHelp(self):
+        """CLAppTester: getHelp() functions as expected """
+        app = CLAppTester()
+        self.assertEqual(app.getHelp(), 'Duh')
+
+    def test_handle_app_result_build_failure(self):
+        """_handle_app_result_build_failure on CommandLineAppResult() failure
+        """
+        app = CLAppTester_bad_fixed_file()
+        self.assertRaises(ApplicationError, app)
+
+        app = CLAppTester_bad_fixed_file_w_handler()
+        self.assertEqual(app(),
+                         "Called self._handle_app_result_build_failure")
+
+    def test_error_on_missing_executable(self):
+        """CLAppTester: Useful error message on executable not found
+        """
+
+        # fake command via self._command
+        class Blah(CLAppTester):
+            _command = 'fake_command_jasdlkfsadlkfskladfkladf'
+
+        self.assertRaises(ApplicationNotFoundError, Blah)
+
+        # real command but bad path via self._command
+        class Blah(CLAppTester):
+            _command = '/not/a/real/path/ls'
+
+        self.assertRaises(ApplicationNotFoundError, Blah)
+
+        # alt _error_on_missing_command function works as expected
+        class Blah(CLAppTester):
+            _command = 'ls'
+
+            def _error_on_missing_application(self, data):
+                raise ApplicationNotFoundError
+
+        self.assertRaises(ApplicationNotFoundError, Blah)
+
+        class Blah(CLAppTester):
+            _command = 'fake_app_asfasdasdasdasdasd'
+
+            def _error_on_missing_application(self, data):
+                pass
+
+        # no error raised
+        Blah()
+
+    def test_no_p_no_d(self):
+        """CLAppTester: parameters turned off, no data"""
+        app = self.app_no_params
+        # test_init
+        assert app.Parameters['-F'].isOff()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # test_command
+        self.assertEqual(app.BaseCommand, 'cd "/tmp/"; /tmp/CLAppTester.py')
+        # test_result
+        result = app()
+        self.assertEqual(result['StdOut'].read(), 'out\n')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+        self.assertEqual(result['parameterized_file'], None)
+        result.cleanUp()
+
+    def test_no_p_data_as_str(self):
+        """CLAppTester: parameters turned off, data as string"""
+        app = self.app_no_params
+        # test_init
+        assert app.Parameters['-F'].isOff()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # test_command
+        self.assertEqual(app.BaseCommand, 'cd "/tmp/"; /tmp/CLAppTester.py')
+        # test_result
+        result = app(self.data)
+        self.assertEqual(result['StdOut'].read(), 'out 43\n')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+        self.assertEqual(result['parameterized_file'], None)
+        result.cleanUp()
+
+    def test_p_data_as_str_suppress_stderr(self):
+        """CLAppTester: parameters turned on, data as string, suppress stderr
+        """
+        app = self.app_params_no_stderr
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert app.SuppressStderr
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; /tmp/CLAppTester.py -F "p_file.txt"')
+        # test_result
+        result = app(self.data)
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'], None)
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out 43 p_file.txt')
+        result.cleanUp()
+
+    def test_p_data_as_str_suppress_stdout(self):
+        """CLAppTester: parameters turned on, data as string, suppress stdout
+        """
+        app = self.app_params_no_stdout
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert app.SuppressStdout
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; /tmp/CLAppTester.py -F "p_file.txt"')
+        # test_result
+        result = app(self.data)
+        self.assertEqual(result['StdOut'], None)
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out 43 p_file.txt')
+        result.cleanUp()
+
+    def test_p_no_data(self):
+        """CLAppTester: parameters turned on, no data"""
+        app = self.app_params
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; /tmp/CLAppTester.py -F "p_file.txt"')
+        # test_result
+        result = app()
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out p_file.txt')
+        result.cleanUp()
+
+    def test_p_space_in_command(self):
+        """CLAppTester: parameters turned on, no data, space in command"""
+        app = self.app_params_space_in_command
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; "/tmp/CLApp Tester.py" -F "p_file.txt"')
+        # test_result
+        result = app()
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out p_file.txt')
+        result.cleanUp()
+
+    def test_p_data_as_str(self):
+        """CLAppTester: parameters turned on, data as str"""
+        app = self.app_params
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; /tmp/CLAppTester.py -F "p_file.txt"')
+        # test_result
+        result = app(self.data)
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out 43 p_file.txt')
+        result.cleanUp()
+
+    def test_p_data_as_file(self):
+        """CLAppTester: parameters turned on, data as file"""
+        app = self.app_params_input_as_file
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_lines')
+        assert not app.SuppressStderr
+        # test_command
+        # we don't test the command in this case, because we don't know what
+        # the name of the input file is.
+        # test_result
+        result = app([self.data])
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out 43 p_file.txt')
+        result.cleanUp()
+
+    def test_WorkingDir(self):
+        """CLAppTester: WorkingDir functions as expected """
+        system('cp /tmp/CLAppTester.py /tmp/test/CLAppTester.py')
+        app = self.app_params_WorkingDir
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # WorkingDir is what we expect
+        self.assertEqual(app.WorkingDir, '/tmp/test/')
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         ('cd "/tmp/test/"; /tmp/CLAppTester.py '
+                          '-F "p_file.txt"'))
+        # test_result
+        result = app()
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+
+        # Make sure that the parameterized file is in the correct place
+        self.assertEqual(result['parameterized_file'].name,
+                         '/tmp/test/p_file.txt')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out p_file.txt')
+        result.cleanUp()
+
+    def test_WorkingDir_w_space(self):
+        """CLAppTester: WorkingDir w/ space in path functions as expected """
+        system('cp /tmp/CLAppTester.py "/tmp/test space/CLAppTester.py"')
+        app = self.app_params_WorkingDir_w_space
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # WorkingDir is what we expect
+        self.assertEqual(app.WorkingDir, '/tmp/test space/')
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         ('cd "/tmp/test space/"; /tmp/CLAppTester.py'
+                          ' -F "p_file.txt"'))
+        # test_result
+        result = app()
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+
+        # Make sure that the parameterized file is in the correct place
+        self.assertEqual(result['parameterized_file'].name,
+                         '/tmp/test space/p_file.txt')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out p_file.txt')
+        result.cleanUp()
+
+    def test_TmpDir(self):
+        """CLAppTester: Alternative TmpDir functions as expected"""
+        app = self.app_params_TmpDir
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # TmpDir is what we expect
+        self.assertEqual(app.TmpDir, '/tmp/tmp2/')
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; /tmp/CLAppTester.py -F "p_file.txt"')
+        # test_result
+        result = app()
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+
+        # Make sure that the parameterized file is in the correct place
+        self.assertEqual(result['parameterized_file'].name,
+                         '/tmp/p_file.txt')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out p_file.txt')
+        result.cleanUp()
+
+    def test_TmpDir_w_space(self):
+        """CLAppTester: TmpDir functions as expected w space in name"""
+        app = self.app_params_TmpDir_w_space
+        # test_init
+        assert app.Parameters['-F'].isOn()
+        self.assertEqual(app.InputHandler, '_input_as_string')
+        assert not app.SuppressStderr
+        # TmpDir is what we expect
+        self.assertEqual(app.TmpDir, '/tmp/tmp space/')
+        # test_command
+        self.assertEqual(app.BaseCommand,
+                         'cd "/tmp/"; /tmp/CLAppTester.py -F "p_file.txt"')
+        # test_result
+        result = app()
+        self.assertEqual(result['StdOut'].read(), '')
+        self.assertEqual(result['StdErr'].read(), 'I am stderr\n')
+        self.assertEqual(result['ExitStatus'], 0)
+        self.assertEqual(result['fixed_file'].read(), 'I am fixed file')
+        self.assertEqual(result['base_dep_1'].read(), 'base dependent 1')
+        self.assertEqual(result['base_dep_2'].read(), 'base dependent 2')
+
+        # Make sure that the parameterized file is in the correct place
+        self.assertEqual(result['parameterized_file'].name,
+                         '/tmp/p_file.txt')
+        self.assertEqual(result['parameterized_file'].read(),
+                         'out p_file.txt')
+        result.cleanUp()
+
+    def test_input_as_string(self):
+        """CLAppTester: _input_as_string functions as expected """
+        self.assertEqual(self.app_no_params._input_as_string('abcd'), 'abcd')
+        self.assertEqual(self.app_no_params._input_as_string(42), '42')
+        self.assertEqual(self.app_no_params._input_as_string(None), 'None')
+        self.assertEqual(self.app_no_params._input_as_string([1]), '[1]')
+        self.assertEqual(self.app_no_params._input_as_string({'a': 1}),
+                         "{'a': 1}")
+
+    def test_input_as_lines_from_string(self):
+        """CLAppTester: _input_as_lines functions as expected w/ data as str
+        """
+        filename = self.app_no_params._input_as_lines('abcd')
+        self.assertEqual(filename[0], '/')
+        f = open(filename)
+        self.assertEqual(f.readline(), 'a\n')
+        self.assertEqual(f.readline(), 'b\n')
+        self.assertEqual(f.readline(), 'c\n')
+        self.assertEqual(f.readline(), 'd')
+        f.close()
+        remove(filename)
+
+    def test_input_as_lines_from_list(self):
+        """CLAppTester: _input_as_lines functions as expected w/ data as list
+        """
+        filename = self.app_no_params._input_as_lines(['line 1', None, 3])
+        self.assertEqual(filename[0], '/')
+        f = open(filename)
+        self.assertEqual(f.readline(), 'line 1\n')
+        self.assertEqual(f.readline(), 'None\n')
+        self.assertEqual(f.readline(), '3')
+        f.close()
+        remove(filename)
+
+    def test_input_as_lines_from_list_w_newlines(self):
+        """CLAppTester: _input_as_lines functions w/ data as list w/ newlines
+        """
+        filename = self.app_no_params._input_as_lines(['line 1\n', None, 3])
+        self.assertEqual(filename[0], '/')
+        f = open(filename)
+        self.assertEqual(f.readline(), 'line 1\n')
+        self.assertEqual(f.readline(), 'None\n')
+        self.assertEqual(f.readline(), '3')
+        f.close()
+        remove(filename)
+
+    def test_input_as_multiline_string(self):
+        """CLAppTester: _input_as_multiline_string functions as expected
+        """
+        filename = self.app_no_params._input_as_multiline_string(
+            'line 1\nNone\n3')
+        self.assertEqual(filename[0], '/')
+        f = open(filename)
+        self.assertEqual(f.readline(), 'line 1\n')
+        self.assertEqual(f.readline(), 'None\n')
+        self.assertEqual(f.readline(), '3')
+        f.close()
+        remove(filename)
+
+    def test_input_as_lines_from_list_single_entry(self):
+        """CLAppTester: _input_as_lines functions as expected w/ 1 element list
+        """
+        filename = self.app_no_params._input_as_lines(['line 1'])
+        self.assertEqual(filename[0], '/')
+        f = open(filename)
+        self.assertEqual(f.readline(), 'line 1')
+        f.close()
+        remove(filename)
+
+    def test_input_as_multiline_string_single_line(self):
+        """CLAppTester: _input_as_multiline_string functions w/ single line
+        """
+        # functions as expected with single line string
+        filename = self.app_no_params._input_as_multiline_string(
+            'line 1')
+        self.assertEqual(filename[0], '/')
+        f = open(filename)
+        self.assertEqual(f.readline(), 'line 1')
+        f.close()
+        remove(filename)
+
+    def test_getTmpFilename_non_default(self):
+        """TmpFilename handles alt tmp_dir, prefix and suffix properly"""
+        app = CLAppTester()
+        obs = app.getTmpFilename(include_class_id=False)
+        self.assertTrue(obs.startswith(app.TmpDir + 'tmp'))
+        self.assertTrue(obs.endswith('.txt'))
+
+        obs = app.getTmpFilename(tmp_dir="/tmp/blah", prefix="app_ctl_test",
+                                 suffix='.test', include_class_id=False)
+        self.assertTrue(obs.startswith('/tmp/blah/app_ctl_test'))
+        self.assertTrue(obs.endswith('.test'))
+
+    def test_getTmpFilename_defaults_to_no_class_id(self):
+        """CLAppTester: getTmpFilename doesn't include class id by default
+        """
+        # I want to explicitly test for this so people don't forget to
+        # set the default to False if they change it for testing purposes
+        app = CLAppTester()
+        self.assertFalse(app.getTmpFilename().
+                         startswith(app.TmpDir + 'tmpCLAppTester'))
+        self.assertTrue(app.getTmpFilename(include_class_id=True).
+                        startswith(app.TmpDir + 'tmpCLAppTester'))
+
+    def test_input_as_path(self):
+        """CLAppTester: _input_as_path casts data to FilePath"""
+        actual = self.app_no_params._input_as_path('test.pdb')
+        self.assertEqual(actual, 'test.pdb')
+        self.assertEqual(str(actual), '"test.pdb"')
+        actual = self.app_no_params._input_as_path('te st.pdb')
+        self.assertEqual(actual, 'te st.pdb')
+        self.assertEqual(str(actual), '"te st.pdb"')
+        actual = self.app_no_params._input_as_path('./test.pdb')
+        self.assertEqual(actual, './test.pdb')
+        self.assertEqual(str(actual), '"./test.pdb"')
+        actual = self.app_no_params._input_as_path('/this/is/a/test.pdb')
+        self.assertEqual(actual, '/this/is/a/test.pdb')
+        self.assertEqual(str(actual), '"/this/is/a/test.pdb"')
+        actual = self.app_no_params._input_as_path('/this/i s/a/test.pdb')
+        self.assertEqual(actual, '/this/i s/a/test.pdb')
+        self.assertEqual(str(actual), '"/this/i s/a/test.pdb"')
+
+    def test_input_as_paths(self):
+        """CLAppTester: _input_as_paths casts each input to FilePath """
+        input = ['test.pdb']
+        actual = self.app_no_params._input_as_paths(input)
+        expected = '"test.pdb"'
+        self.assertEqual(actual, expected)
+
+        input = ['test1.pdb', 'test2.pdb']
+        actual = self.app_no_params._input_as_paths(input)
+        expected = '"test1.pdb" "test2.pdb"'
+        self.assertEqual(actual, expected)
+
+        input = ['/path/to/test1.pdb', 'test2.pdb']
+        actual = self.app_no_params._input_as_paths(input)
+        expected = '"/path/to/test1.pdb" "test2.pdb"'
+        self.assertEqual(actual, expected)
+
+        input = ['test1.pdb', '/path/to/test2.pdb']
+        actual = self.app_no_params._input_as_paths(input)
+        expected = '"test1.pdb" "/path/to/test2.pdb"'
+        self.assertEqual(actual, expected)
+
+        input = ['/path/to/test1.pdb', '/path/to/test2.pdb']
+        actual = self.app_no_params._input_as_paths(input)
+        expected = '"/path/to/test1.pdb" "/path/to/test2.pdb"'
+        self.assertEqual(actual, expected)
+
+        input = ['/pa th/to/test1.pdb', '/path/to/te st2.pdb']
+        actual = self.app_no_params._input_as_paths(input)
+        expected = '"/pa th/to/test1.pdb" "/path/to/te st2.pdb"'
+        self.assertEqual(actual, expected)
+
+    def test_absolute(self):
+        """CLAppTester: _absolute converts relative paths to absolute paths
+        """
+        absolute = self.app_no_params._absolute
+        self.assertEqual(absolute('/tmp/test.pdb'), '/tmp/test.pdb')
+        self.assertEqual(absolute('test.pdb'), '/tmp/test.pdb')
+
+    def test_working_dir_setting(self):
+        """CLAppTester: WorkingDir is set correctly """
+        app = CLAppTester_no_working_dir()
+        self.assertEqual(app.WorkingDir, getcwd() + '/')
+
+    def test_error_raised_on_command_None(self):
+        """CLAppTester: An error is raises when _command == None """
+        app = CLAppTester()
+        app._command = None
+        self.assertRaises(ApplicationError, app._get_base_command)
+
+    def test_rejected_exit_status(self):
+        """CLAppTester_reject_exit_status results in useful error """
+        app = CLAppTester_reject_exit_status()
+        self.assertRaises(ApplicationError, app)
+
+    def test_getTmpFilename(self):
+        """TmpFilename should return filename of correct length"""
+        app = CLAppTester()
+        obs = app.getTmpFilename(include_class_id=True)
+        # leaving the strings in this statement so it's clear where the
+        # expected length comes from
+        self.assertEqual(len(obs), len(app.TmpDir) + app.TmpNameLen +
+                         len('tmp') + len('CLAppTester') + len('.txt'))
+        assert obs.startswith(app.TmpDir)
+        chars = set(obs[18:])
+        assert len(chars) > 1
+
+        obs = app.getTmpFilename(include_class_id=False)
+        # leaving the strings in this statement so it's clear where the
+        # expected length comes from
+        self.assertEqual(len(obs), len(app.TmpDir) + app.TmpNameLen +
+                         len('tmp') + len('.txt'))
+        assert obs.startswith(app.TmpDir)
+
+    def test_getTmpFilename_prefix_suffix_result_constructor(self):
+        """TmpFilename: result has correct prefix, suffix, type"""
+        app = CLAppTester()
+        obs = app.getTmpFilename(prefix='blah', include_class_id=False)
+        self.assertTrue(obs.startswith(app.TmpDir + 'blah'))
+        obs = app.getTmpFilename(suffix='.blah', include_class_id=False)
+        self.assertTrue(obs.endswith('.blah'))
+        # Prefix defaults to not include the class name
+        obs = app.getTmpFilename(include_class_id=False)
+        self.assertFalse(obs.startswith(app.TmpDir + 'tmpCLAppTester'))
+        self.assertTrue(obs.endswith('.txt'))
+        # including class id functions correctly
+        obs = app.getTmpFilename(include_class_id=True)
+        self.assertTrue(obs.startswith(app.TmpDir + 'tmpCLAppTester'))
+        self.assertTrue(obs.endswith('.txt'))
+
+        # result as FilePath
+        obs = app.getTmpFilename(result_constructor=FilePath)
+        self.assertEqual(type(obs), FilePath)
+
+        # result as str (must check that result is a str and is not a FilePath
+        # since a FilePath is a str)
+        obs = app.getTmpFilename(result_constructor=str)
+        self.assertEqual(type(obs), str)
+        self.assertNotEqual(type(obs), FilePath)
+
+
+class ConvenienceFunctionTests(TestCase):
+
+    """
+    """
+
+    def setUp(self):
+        """
+        """
+        self.tmp_dir = gettempdir()
+        self.tmp_name_len = 20
+
+    def test_guess_input_handler(self):
+        """guess_input_handler should correctly identify input"""
+        gih = guess_input_handler
+        self.assertEqual(gih('abc.txt'), '_input_as_string')
+        self.assertEqual(gih('>ab\nTCAG'), '_input_as_multiline_string')
+        self.assertEqual(gih(['ACC', 'TGA'], True), '_input_as_seqs')
+        self.assertEqual(gih(['>a', 'ACC', '>b', 'TGA']), '_input_as_lines')
+        self.assertEqual(gih([('a', 'ACC'), ('b', 'TGA')]),
+                         '_input_as_seq_id_seq_pairs')
+        self.assertEqual(gih([]), '_input_as_lines')
+
+    def test_get_tmp_filename(self):
+        """get_tmp_filename should return filename of correct length
+
+            Adapted from the CommandLineApplication tests of the member
+            function
+
+        """
+        obs = get_tmp_filename()
+        # leaving the strings in this statement so it's clear where the
+        # expected length comes from
+        self.assertEqual(len(obs),
+                         len(self.tmp_dir) + len('/') + self.tmp_name_len +
+                         len('tmp') + len('.txt'))
+        self.assertTrue(obs.startswith(self.tmp_dir))
+
+        # different results on different calls
+        self.assertNotEqual(get_tmp_filename(), get_tmp_filename())
+
+        obs = get_tmp_filename()
+        # leaving the strings in this statement so it's clear where the
+        # expected length comes from
+        self.assertEqual(len(obs),
+                         len(self.tmp_dir) + len('/') + self.tmp_name_len +
+                         len('tmp') + len('.txt'))
+        assert obs.startswith(self.tmp_dir)
+
+    def test_get_tmp_filename_prefix_suffix_constructor(self):
+        """get_tmp_filename: result has correct prefix, suffix, type
+
+            Adapted from the CommandLineApplication tests of the member
+            function
+        """
+        obs = get_tmp_filename(prefix='blah')
+        self.assertTrue(obs.startswith('%s/blah' % self.tmp_dir))
+        obs = get_tmp_filename(suffix='.blah')
+        self.assertTrue(obs.endswith('.blah'))
+
+        # result as FilePath
+        obs = get_tmp_filename(result_constructor=FilePath)
+        self.assertEqual(type(obs), FilePath)
+
+        # result as str (must check that result is a str and is not a FilePath
+        # since a FilePath is a str)
+        obs = get_tmp_filename(result_constructor=str)
+        self.assertEqual(type(obs), str)
+        self.assertNotEqual(type(obs), FilePath)
+
+    def test_which_found(self):
+        """Test finding filepath for executable that can be found."""
+        obs = which('ls')
+        self.assertTrue(obs is not None)
+        self.assertTrue(exists(obs))
+
+    def test_which_not_found(self):
+        """Test finding filepath for executable that cannot be found."""
+        obs = which('thiscommandhadbetternotexist')
+        self.assertTrue(obs is None)
+
+    def test_which_env_var(self):
+        """Test finding filepath using an env_var other than the default."""
+        obs = which('ls', env_var='THISENVVARHADBETTERNOTEXIST')
+        self.assertTrue(obs is None)
+
+
+def teardown_module():
+    """This will remove the test script."""
+    for dir, n, fnames in walk('/tmp/test/'):
+        for f in fnames:
+            try:
+                remove(dir + f)
+            except OSError:
+                pass
+
+    remove('/tmp/CLAppTester.py')
+    remove('/tmp/test space/CLAppTester.py')
+    remove('/tmp/CLApp Tester.py')
+    rmdir('/tmp/tmp space')
+    rmdir('/tmp/test')
+    rmdir('/tmp/test space')
+    rmdir('/tmp/tmp2')
+    rmdir('/tmp/blah')
+
+
+# =====================END OF TESTS==================================
+
+script = """#!/usr/bin/env python
+#This is a test script intended to test the CommandLineApplication
+#class and CommandLineAppResult class
+
+from __future__ import absolute_import, division, print_function
+
+from sys import argv, stderr, stdin
+from os import isatty
+
+out_file_name = None
+
+input_arg = None
+
+# parse input
+try:
+    if argv[1] == '-F':
+        out_file_name = argv[2]
+except IndexError:
+    pass
+try:
+    if out_file_name:
+        input_arg = argv[3]
+    else:
+        input_arg = argv[1]
+except IndexError:
+    pass
+# Create the output string
+out = 'out'
+# get input
+try:
+    f = open(str(input_arg))
+    data = int(f.readline().strip())
+except IOError:
+    try:
+        data = int(input_arg)
+    except TypeError:
+        data = None
+
+if data:
+    data = str(data + 1)
+    out = ' '.join([out,data])
+
+# Write base dependent output files
+base = 'BASE'
+f = open('/tmp/' + base + '.1','w')
+f.writelines(['base dependent 1'])
+f.close()
+f = open('/tmp/' + base + '.2','w')
+f.writelines(['base dependent 2'])
+f.close()
+
+# If output to file, open the file and write output to it
+if out_file_name:
+    filename = argv[2]
+    f = open(''.join([out_file_name]),'w')
+    out = ' '.join([out,out_file_name])
+    f.writelines(out)
+    f.close()
+else:
+    print(out)
+
+#generate some stderr
+print('I am stderr', file=stderr)
+
+# Write the fixed file
+f = open('/tmp/fixed.txt','w')
+f.writelines(['I am fixed file'])
+f.close()
+
+"""
+
+
+class CLAppTester(CommandLineApplication):
+    _parameters = {
+        '-F': ValuedParameter(Prefix='-', Name='F', Delimiter=' ',
+                              Value=None, Quote="\""),
+        '--duh': FlagParameter(Prefix='--', Name='duh')}
+    _command = '/tmp/CLAppTester.py'
+    _synonyms = {'File': '-F', 'file': '-F'}
+    _working_dir = '/tmp'
+
+    def _get_result_paths(self, data):
+
+        if self.Parameters['-F'].isOn():
+            param_path = ''.join(
+                [self.WorkingDir, self.Parameters['-F'].Value])
+        else:
+            param_path = None
+
+        result = {}
+        result['fixed_file'] = ResultPath(Path='/tmp/fixed.txt')
+        result['parameterized_file'] = \
+            ResultPath(Path=param_path,
+                       IsWritten=self.Parameters['-F'].isOn())
+        result['base_dep_1'] = ResultPath(Path=self._build_name(suffix='.1'))
+        result['base_dep_2'] = ResultPath(Path=self._build_name(suffix='.2'))
+        return result
+
+    def _build_name(self, suffix):
+        return '/tmp/BASE' + suffix
+
+    def getHelp(self):
+        return """Duh"""
+
+
+class CLAppTester_no_working_dir(CLAppTester):
+    _working_dir = None
+
+
+class CLAppTester_reject_exit_status(CLAppTester):
+
+    def _accept_exit_status(self, exit_status):
+        return False
+
+
+class CLAppTester_bad_fixed_file(CLAppTester):
+
+    def _get_result_paths(self, data):
+
+        if self.Parameters['-F'].isOn():
+            param_path = ''.join(
+                [self.WorkingDir, self.Parameters['-F'].Value])
+        else:
+            param_path = None
+
+        result = {}
+        result['fixed_file'] = ResultPath(Path='/tmp/fixed.txt')
+        result['fixed_file_bad'] = ResultPath(Path='/tmp/i_dont_exist.txt')
+        result['parameterized_file'] = \
+            ResultPath(Path=param_path,
+                       IsWritten=self.Parameters['-F'].isOn())
+        result['base_dep_1'] = ResultPath(Path=self._build_name(suffix='.1'))
+        result['base_dep_2'] = ResultPath(Path=self._build_name(suffix='.2'))
+        return result
+
+
+class CLAppTester_bad_fixed_file_w_handler(CLAppTester_bad_fixed_file):
+
+    def _handle_app_result_build_failure(
+            self,
+            out,
+            err,
+            exit_status,
+            result_paths):
+        return "Called self._handle_app_result_build_failure"
+
+
+class CLAppTester_space_in_command(CLAppTester):
+    _command = '"/tmp/CLApp Tester.py"'
+
+
+class ParameterCombinationsApp(CommandLineApplication):
+
+    """ParameterCombinations mock application to wrap"""
+    _command = 'testcmd'
+    _parameters = {'-flag1': FlagParameter(Prefix='-', Name='flag1'),
+                   '-flag2': FlagParameter(Prefix='-', Name='flag2'),
+                   '--value1': ValuedParameter(Prefix='--', Name='value1'),
+                   '-value2': ValuedParameter(Prefix='-', Name='value2'),
+                   '-mix1': MixedParameter(Prefix='-', Name='mix1'),
+                   '-mix2': MixedParameter(Prefix='-', Name='mix2'),
+                   '-delim': ValuedParameter(Prefix='-', Name='delim',
+                                             Delimiter='aaa'),
+                   '-default': ValuedParameter(Prefix='-', Name='default',
+                                               Value=42, Delimiter='='),
+                   '-input': ValuedParameter(Prefix='-', Name='input',
+                                             Delimiter='='),
+                   '-output': ValuedParameter(Prefix='-', Name='output',
+                                              Delimiter='=')}
+if __name__ == '__main__':
+    from nose import runmodule
+    runmodule()
diff --git a/burrito/util.py b/burrito/util.py
new file mode 100644
index 0000000..1116ed3
--- /dev/null
+++ b/burrito/util.py
@@ -0,0 +1,791 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2014--, burrito development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# ----------------------------------------------------------------------------
+
+from future.utils import implements_iterator
+
+import os
+from os import remove, system, mkdir, getcwd
+from os.path import isabs, exists
+from random import choice
+from tempfile import gettempdir
+from copy import deepcopy
+from itertools import product
+
+from burrito.parameters import Parameters, FilePath
+
+# the following are used to create temp file names
+from string import ascii_letters, digits
+_all_chars = ascii_letters + digits
+
+
+def which(executable_name, env_var='PATH'):
+    """Equivalent to ``which executable_name`` in a *nix environment.
+
+    Will return ``None`` if ``executable_name`` cannot be found in ``env_var``
+    or if ``env_var`` is not set. Otherwise will return the first match in
+    ``env_var``.
+
+    Note: this function will likely not work on Windows.
+
+    Code taken and modified from:
+        http://www.velocityreviews.com/forums/
+        t689526-python-library-call-equivalent-to-which-command.html
+
+    """
+    exec_fp = None
+
+    if env_var in os.environ:
+        paths = os.environ[env_var]
+
+        for path in paths.split(os.pathsep):
+            curr_exec_fp = os.path.join(path, executable_name)
+
+            if os.access(curr_exec_fp, os.X_OK):
+                exec_fp = curr_exec_fp
+                break
+
+    return exec_fp
+
+
+class ApplicationError(OSError):
+    pass
+
+
+class ApplicationNotFoundError(ApplicationError):
+    pass
+
+
+class ResultPath(object):
+
+    """ Hold a file path a boolean value specifying whether file was written
+    """
+
+    def __init__(self, Path, IsWritten=True):
+        """ Initialize the ResultPath object
+
+            Path: a string representing the absolute or relative path where
+                the file can be found
+            IsWritten: a boolean specifying whether the file has been written,
+                default = True
+        """
+        self.Path = FilePath(Path)
+        self.IsWritten = IsWritten
+
+
+class CommandLineAppResult(dict):
+
+    """ Class for holding the result of a CommandLineApplication run """
+
+    def __init__(self, out, err, exit_status, result_paths):
+        """Initialization of CommandLineAppResult
+
+        out: a file handler to the file containing the stdout
+        err: a file handler to the file containing the stderr
+        exit_status: the exit status of the program, 0 if run ok, 1 else.
+        result_paths: dictionary containing ResultPath objects for each
+            output file that could be written
+        """
+
+        self['StdOut'] = out
+        self['StdErr'] = err
+        self['ExitStatus'] = exit_status
+
+        self.file_keys = result_paths.keys()
+        for key, value in result_paths.items():
+            if value.IsWritten:
+                try:
+                    self[key] = open(value.Path)
+                except IOError:
+                    raise ApplicationError('Could not open %s' % value.Path)
+            else:
+                self[key] = None
+
+    def cleanUp(self):
+        """ Delete files that are written by CommandLineApplication from disk
+
+            WARNING: after cleanUp() you may still have access to part of
+                your result data, but you should be aware that if the file
+                size exceeds the size of the buffer you will only have part
+                of the file. To be safe, you should not use cleanUp() until
+                you are done with the file or have copied it to a different
+                location.
+        """
+        file_keys = self.file_keys
+        for item in file_keys:
+            if self[item] is not None:
+                self[item].close()
+                remove(self[item].name)
+
+        # remove input handler temp files
+        if hasattr(self, "_input_filename"):
+            remove(self._input_filename)
+
+    def __del__(self):
+        """ Delete temporary files created by the CommandLineApplication
+        """
+        if self['StdOut'] is not None:
+            remove(self['StdOut'].name)
+        if self['StdErr'] is not None:
+            remove(self['StdErr'].name)
+
+
+class Application(object):
+
+    """ Generic Class for controlling an application """
+
+    _command = None
+    _command_delimiter = ' '
+    _parameters = {}
+    _synonyms = {}
+
+    def __init__(self, params=None):
+        """
+            params: a dict of parameters which should be turned on where the
+                key is either the parameter id or a synonym for the parameter
+                and the value is either the value for the parameter or None
+        """
+        self.Parameters = Parameters(self._parameters, self._synonyms)
+        if params:
+            for key, v in params.items():
+                try:
+                    self.Parameters[key].on(v)
+                except TypeError:
+                    self.Parameters[key].on()
+
+
+class CommandLineApplication(Application):
+
+    """ Generic class for controlling command line applications
+    """
+
+    _input_handler = '_input_as_string'
+    _suppress_stderr = False
+    _suppress_stdout = False
+    _working_dir = None
+
+    def __init__(self, params=None, InputHandler=None, SuppressStderr=None,
+                 SuppressStdout=None, WorkingDir=None, TmpDir=gettempdir(),
+                 TmpNameLen=20, HALT_EXEC=False):
+        """ Initialize the CommandLineApplication object
+
+            params: a dictionary mapping the Parameter id or synonym to its
+                value (or None for FlagParameters or MixedParameters in flag
+                mode) for Parameters that should be turned on
+            InputHandler: this is the method to be run on data when it is
+                passed into call. This should be a string containing the
+                method name. The default is _input_as_string which casts data
+                to a string before appending it to the command line argument
+            SuppressStderr: if set to True, will route standard error to
+                /dev/null, False by default
+            SuppressStdout: if set to True, will route standard out to
+                /dev/null, False by default
+            WorkingDir: the directory where you want the application to run,
+                default is the current working directory, but is useful to
+                change in cases where the program being run creates output
+                to its current working directory and you either don't want
+                it to end up where you are running the program, or the user
+                running the script doesn't have write access to the current
+                working directory
+                WARNING: WorkingDir MUST be an absolute path!
+            TmpDir: the directory where temp files will be created
+            TmpNameLen: the length of the temp file name
+            HALT_EXEC: if True, raises exception w/ command output just
+            before execution, doesn't clean up temp files. Default False.
+        """
+        # Determine if the application is installed, and raise an error if not
+        self._error_on_missing_application(params)
+
+        # set attributes to parameter that was passed in or class default
+        if InputHandler is not None:
+            self.InputHandler = InputHandler
+        else:
+            self.InputHandler = self._input_handler
+        if SuppressStderr is not None:
+            self.SuppressStderr = SuppressStderr
+        else:
+            self.SuppressStderr = self._suppress_stderr
+        if SuppressStdout is not None:
+            self.SuppressStdout = SuppressStdout
+        else:
+            self.SuppressStdout = self._suppress_stdout
+        if WorkingDir is not None:
+            working_dir = WorkingDir
+        else:
+            working_dir = self._working_dir or getcwd()
+        self.WorkingDir = FilePath(working_dir)
+        if not TmpDir.endswith("/"):
+            TmpDir += "/"
+        self.TmpDir = FilePath(TmpDir)
+        self.TmpNameLen = TmpNameLen
+        self.HaltExec = HALT_EXEC
+
+        # create a variable to hold the name of the file being used as
+        # input to the application. this is important especially when
+        # you are using an input handler which creates a temporary file
+        # and the output filenames are based on the input filenames
+        self._input_filename = None
+
+        super(CommandLineApplication, self).__init__(params=params)
+
+    def __call__(self, data=None, remove_tmp=True):
+        """Run the application with the specified kwargs on data
+
+            data: anything that can be cast into a string or written out to
+                a file. Usually either a list of things or a single string or
+                number. input_handler will be called on this data before it
+                is passed as part of the command-line argument, so by creating
+                your own input handlers you can customize what kind of data
+                you want your application to accept
+
+            remove_tmp: if True, removes tmp files
+        """
+        input_handler = self.InputHandler
+        suppress_stdout = self.SuppressStdout
+        suppress_stderr = self.SuppressStderr
+        if suppress_stdout:
+            outfile = FilePath('/dev/null')
+        else:
+            outfile = self.getTmpFilename(self.TmpDir)
+        if suppress_stderr:
+            errfile = FilePath('/dev/null')
+        else:
+            errfile = FilePath(self.getTmpFilename(self.TmpDir))
+        if data is None:
+            input_arg = ''
+        else:
+            input_arg = getattr(self, input_handler)(data)
+
+        # Build up the command, consisting of a BaseCommand followed by
+        # input and output (file) specifications
+        command = self._command_delimiter.join(filter(None,
+                                                      [self.BaseCommand,
+                                                       str(input_arg),
+                                                       '>', str(outfile),
+                                                       '2>', str(errfile)]))
+        if self.HaltExec:
+            raise AssertionError("Halted exec with command:\n" + command)
+        # The return value of system is a 16-bit number containing the signal
+        # number that killed the process, and then the exit status.
+        # We only want to keep the exit status so do a right bitwise shift to
+        # get rid of the signal number byte
+        exit_status = system(command) >> 8
+
+        # Determine if error should be raised due to exit status of
+        # appliciation
+        if not self._accept_exit_status(exit_status):
+            raise ApplicationError('Unacceptable application exit ' +
+                                   'status: %s\n' % str(exit_status) +
+                                   'Command:\n%s\n' % command +
+                                   'StdOut:\n%s\n' % open(outfile).read() +
+                                   'StdErr:\n%s\n' % open(errfile).read())
+
+        # open the stdout and stderr if not being suppressed
+        out = None
+        if not suppress_stdout:
+            out = open(outfile, "r")
+        err = None
+        if not suppress_stderr:
+            err = open(errfile, "r")
+
+        result_paths = self._get_result_paths(data)
+        try:
+            result = \
+                CommandLineAppResult(out, err, exit_status,
+                                     result_paths=result_paths)
+        except ApplicationError:
+            result = \
+                self._handle_app_result_build_failure(out, err, exit_status,
+                                                      result_paths)
+
+        # Clean up the input file if one was created
+        if remove_tmp:
+            if self._input_filename:
+                remove(self._input_filename)
+                self._input_filename = None
+
+        return result
+
+    def _handle_app_result_build_failure(
+            self,
+            out,
+            err,
+            exit_status,
+            result_paths):
+        """Called if ApplicationError raised on building CommandLineAppResult
+
+            This is useful for checking log files or other special handling
+             in cases when expected files aren't present.
+
+        """
+        raise ApplicationError("Error constructing CommandLineAppResult.")
+
+    def _input_as_string(self, data):
+        """ Return data as a string """
+        return str(data)
+
+    def _input_as_multiline_string(self, data):
+        """Write a multiline string to a temp file and return the filename.
+
+            data: a multiline string to be written to a file.
+
+           * Note: the result will be the filename as a FilePath object
+            (which is a string subclass).
+
+        """
+        filename = self._input_filename = \
+            FilePath(self.getTmpFilename(self.TmpDir))
+        data_file = open(filename, 'w')
+        data_file.write(data)
+        data_file.close()
+        return filename
+
+    def _input_as_lines(self, data):
+        """ Write a seq of lines to a temp file and return the filename string
+
+            data: a sequence to be written to a file, each element of the
+                sequence will compose a line in the file
+           * Note: the result will be the filename as a FilePath object
+            (which is a string subclass).
+
+           * Note: '\n' will be stripped off the end of each sequence element
+                before writing to a file in order to avoid multiple new lines
+                accidentally be written to a file
+        """
+        filename = self._input_filename = \
+            FilePath(self.getTmpFilename(self.TmpDir))
+        filename = FilePath(filename)
+        data_file = open(filename, 'w')
+        data_to_file = '\n'.join([str(d).strip('\n') for d in data])
+        data_file.write(data_to_file)
+        data_file.close()
+        return filename
+
+    def _input_as_path(self, data):
+        """ Return data as string with the path wrapped in quotes
+
+            data: path or filename, most likely as a string
+
+            * Note: the result will be the filename as a FilePath object
+            (which is a string subclass).
+
+        """
+        return FilePath(data)
+
+    def _input_as_paths(self, data):
+        """ Return data as a space delimited string with each path quoted
+
+            data: paths or filenames, most likely as a list of
+             strings
+
+        """
+        return self._command_delimiter.join(
+            map(str, map(self._input_as_path, data)))
+
+    def _absolute(self, path):
+        """ Convert a filename to an absolute path """
+        path = FilePath(path)
+        if isabs(path):
+            return path
+        else:
+            # these are both Path objects, so joining with + is acceptable
+            return self.WorkingDir + path
+
+    def _get_base_command(self):
+        """ Returns the full command string
+
+            input_arg: the argument to the command which represents the input
+                to the program, this will be a string, either
+                representing input or a filename to get input from
+         tI"""
+        command_parts = []
+        # Append a change directory to the beginning of the command to change
+        # to self.WorkingDir before running the command
+        # WorkingDir should be in quotes -- filenames might contain spaces
+        cd_command = ''.join(['cd ', str(self.WorkingDir), ';'])
+        if self._command is None:
+            raise ApplicationError('_command has not been set.')
+        command = self._command
+        parameters = self.Parameters
+
+        command_parts.append(cd_command)
+        command_parts.append(command)
+        command_parts.append(self._command_delimiter.join(filter(
+            None, (map(str, parameters.values())))))
+
+        return self._command_delimiter.join(command_parts).strip()
+
+    BaseCommand = property(_get_base_command)
+
+    def _get_WorkingDir(self):
+        """Gets the working directory"""
+        return self._curr_working_dir
+
+    def _set_WorkingDir(self, path):
+        """Sets the working directory
+
+        Appends a slash to the end of path
+        The reasoning behind this is that the user may or may not pass
+        in a path with a '/' at the end. Since having multiple
+        '/' at the end doesn't hurt anything, it's convienient to
+        be able to rely on it, and not have to check for it
+        """
+        self._curr_working_dir = FilePath(path) + '/'
+        try:
+            mkdir(self.WorkingDir)
+        except OSError:
+            # Directory already exists
+            pass
+
+    WorkingDir = property(_get_WorkingDir, _set_WorkingDir)
+
+    def _error_on_missing_application(self, params):
+        """ Raise an ApplicationNotFoundError if the app is not accessible
+
+            This method checks in the system path (usually $PATH) or for
+            the existence of self._command. If self._command is not found
+            in either place, an ApplicationNotFoundError is raised to
+            inform the user that the application they are trying to access is
+            not available.
+
+            This method should be overwritten when self._command does not
+            represent the relevant executable (e.g., self._command = 'prog -a')
+            or in more complex cases where the file to be executed may be
+            passed as a parameter (e.g., with java jar files, where the
+            jar file is passed to java via '-jar'). It can also be overwritten
+            to by-pass testing for application presence by never raising an
+            error.
+        """
+        command = self._command
+        # strip off " characters, in case we got a FilePath object
+        found_in_path = which(command.strip('"')) is not None
+        if not (exists(command) or found_in_path):
+            raise ApplicationNotFoundError("Cannot find %s. Is it installed? "
+                                           "Is it in your path?" % command)
+
+    def _accept_exit_status(self, exit_status):
+        """ Return False to raise an error due to exit_status of applciation
+
+            This method should be overwritten if you'd like to raise an error
+            based on certain exit statuses of the application that was run. The
+            default is that no value of exit_status will raise an error.
+        """
+        return True
+
+    def _get_result_paths(self, data):
+        """ Return dict of ResultPath objects representing all possible output
+
+            This method should be overwritten if the application creates
+            output other than stdout and stderr.  This dictionary will have
+            keys based on the name that you'd like to access the file by in
+            the CommandLineAppResult object that will be created, and the
+            values which are ResultPath objects. For an example of how this
+            should be written see the rnaview or vienna_package classes.
+            WARNING: be sure that the path that you give a file is accurate
+                from any directory where the program could be running. For
+                that reason, absolute paths are very good. Relative paths
+                can also be used as long as you are careful. For cases where
+                the application leaves files in the current working directory,
+                you should append self.WorkingDir to the beginning of the file
+                name. It would be a very bad idea to just use a file name as
+                the path, in some cases that you might not be testing for.
+        """
+        return {}
+
+    def getTmpFilename(self, tmp_dir=None, prefix='tmp', suffix='.txt',
+                       include_class_id=False, result_constructor=FilePath):
+        """ Return a temp filename
+
+            tmp_dir: directory where temporary files will be stored
+            prefix: text to append to start of file name
+            suffix: text to append to end of file name
+            include_class_id: if True, will append a class identifier (built
+             from the class name) to the filename following prefix. This is
+             False by default b/c there is some string processing overhead
+             in getting the class name. This will probably be most useful for
+             testing: if temp files are being left behind by tests, you can
+             turn this on in here (temporarily) to find out which tests are
+             leaving the temp files.
+            result_constructor: the constructor used to build the result
+             (default: cogent.app.parameters.FilePath). Note that joining
+             FilePath objects with one another or with strings, you must use
+             the + operator. If this causes trouble, you can pass str as the
+             the result_constructor.
+        """
+
+        # check not none
+        if not tmp_dir:
+            tmp_dir = self.TmpDir
+        # if not current directory, append "/" if not already on path
+        elif not tmp_dir.endswith("/"):
+            tmp_dir += "/"
+
+        if include_class_id:
+            # Append the classname to the prefix from the class name
+            # so any problematic temp files can be associated with
+            # the class that created them. This should be especially
+            # useful for testing, but is turned off by default to
+            # avoid the string-parsing overhead.
+            class_id = str(self.__class__())
+            prefix = ''.join([prefix,
+                              class_id[class_id.rindex('.') + 1:
+                                       class_id.index(' ')]])
+
+        try:
+            mkdir(tmp_dir)
+        except OSError:
+            # Directory already exists
+            pass
+        # note: it is OK to join FilePath objects with +
+        return result_constructor(tmp_dir) + result_constructor(prefix) + \
+            result_constructor(''.join([choice(_all_chars)
+                                        for i in range(self.TmpNameLen)])) +\
+            result_constructor(suffix)
+
+
+ at implements_iterator
+class ParameterIterBase(object):
+
+    """Base class for parameter iteration objects
+
+    This class provides base functionality for parameter iteration objects.
+    A parameter iteration object acts like a generator and returns
+    parameter dicts of varying values. The specific keys and ranges of values
+    can be specified. Subclasses of this object implement the way in which
+    the parameter values are chosen."""
+
+    def __init__(self, Application, Parameters, AlwaysOn=None):
+        """Initialize the ParameterIterBase
+
+        Application : A CommandLineApplication subclass
+        Parameters  : A dict keyed by the application paramter, value by
+                      the range of parameters to enumerate over. For
+                      FlagParameters, unless specified in AlwaysOn, the value
+                      will cycle between True/False (on/off). For
+                      MixedParameters, include [None] specifically to utilize
+                      flag functionality.
+        AlwaysOn    : List of parameters that will always be on
+
+        Parameters is checked against the applications known parameters, but
+        only performed superficially: only keys are validated. AlwaysOn
+        values must have entries within Parameters.
+
+        NOTE: If the parameter is not specified in AlwaysOn, a False value
+        is appended so that the parameter can be turned off. Multiple False
+        states for a parameter will result if False is specified without
+        adding the parameter to AlwaysOn. If a parameter has a default value,
+        then that parameter is implicitly always on.
+        """
+        self.AppParams = Application._parameters
+
+        # Validate Parameters
+        param_set = set(Parameters.keys())
+        app_param_set = set(self.AppParams.keys())
+        if not param_set.issubset(app_param_set):
+            not_present = str(param_set.difference(app_param_set))
+            raise ValueError(
+                "Parameter(s) %s not present in app" %
+                not_present)
+
+        # Validate AlwaysOn
+        alwayson_set = set(AlwaysOn)
+        if not alwayson_set.issubset(param_set):
+            not_present = str(alwayson_set.difference(param_set))
+            raise ValueError("AlwaysOn value(s) %s not in Parameters" %
+                             not_present)
+
+        # Make sure all values are lists
+        for k, v in Parameters.items():
+            if not isinstance(v, list):
+                Parameters[k] = [v]
+        _my_params = Parameters
+
+        # Append "off states" to relevant parameters
+        for k in param_set.difference(alwayson_set):
+            _my_params[k].append(False)
+
+        # Create seperate key/value lists preserving index relation
+        self._keys, self._values = zip(*sorted(_my_params.items()))
+
+        # Construct generator
+        self._generator = self._init_generator()
+
+    def _init_generator(self):
+        """Must be implemented in the subclass"""
+        pass
+
+    def _make_app_params(self, values):
+        """Returns app's param dict with values set as described by values
+        """
+        # A deep copy is necessary. Otherwise the dict values refer to
+        # the same object.
+        app_params = deepcopy(self.AppParams)
+        for key, value in zip(self._keys, values):
+            if value is False:
+                app_params[key].off()
+            elif value is True:
+                app_params[key].on()
+            else:
+                app_params[key].on(value)
+        return app_params
+
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        return next(self._generator)
+
+    def reset(self):
+        self._generator = self._init_generator()
+
+
+class ParameterCombinations(ParameterIterBase):
+
+    """Iterates over all combinations of parameters lexiographically"""
+
+    def _init_generator(self):
+        """Iterates over all possible combinations of parameters
+
+        This method iterates over the cartesian product of parameter values
+        """
+        for vals in product(*self._values):
+            yield self._make_app_params(vals)
+
+
+def cmdline_generator(param_iter, PathToBin=None, PathToCmd=None,
+                      PathsToInputs=None, PathToOutput=None,
+                      PathToStderr='/dev/null', PathToStdout='/dev/null',
+                      UniqueOutputs=False, InputParam=None,
+                      OutputParam=None):
+    """Generates command lines that can be used in a cluster environment
+
+    param_iter : ParameterIterBase subclass instance
+    PathToBin : Absolute location primary command (i.e. Python)
+    PathToCmd : Absolute location of the command
+    PathsToInputs : Absolute location(s) of input file(s)
+    PathToOutput : Absolute location of output file
+    PathToStderr : Path to stderr
+    PathToStdout : Path to stdout
+    UniqueOutputs : Generate unique tags for output files
+    InputParam : Application input parameter (if not specified, assumes
+        stdin is to be used)
+    OutputParam : Application output parameter (if not specified, assumes
+        stdout is to be used)
+    """
+    # Make sure we have input(s) and output
+    if not PathsToInputs:
+        raise ValueError("No input file(s) specified.")
+    if not PathToOutput:
+        raise ValueError("No output file specified.")
+
+    if not isinstance(PathsToInputs, list):
+        PathsToInputs = [PathsToInputs]
+
+    # PathToBin and PathToCmd can be blank
+    if PathToBin is None:
+        PathToBin = ''
+    if PathToCmd is None:
+        PathToCmd = ''
+
+    # stdout_ and stderr_ do not have to be redirected
+    if PathToStdout is None:
+        stdout_ = ''
+    else:
+        stdout_ = '> "%s"' % PathToStdout
+    if PathToStderr is None:
+        stderr_ = ''
+    else:
+        stderr_ = '2> "%s"' % PathToStderr
+
+    # Output can be redirected to stdout or specified output argument
+    if OutputParam is None:
+        output = '> "%s"' % PathToOutput
+        stdout_ = ''
+    else:
+        output_param = param_iter.AppParams[OutputParam]
+        output_param.on('"%s"' % PathToOutput)
+        output = str(output_param)
+        output_param.off()
+
+    output_count = 0
+    base_command = ' '.join([PathToBin, PathToCmd])
+    for params in param_iter:
+        # Support for multiple input files
+        for inputfile in PathsToInputs:
+            cmdline = [base_command]
+            cmdline.extend(sorted(filter(None, map(str, params.values()))))
+
+            # Input can come from stdin or specified input argument
+            if InputParam is None:
+                input = '< "%s"' % inputfile
+            else:
+                input_param = params[InputParam]
+                input_param.on('"%s"' % inputfile)
+                input = str(input_param)
+                input_param.off()
+
+            cmdline.append(input)
+
+            if UniqueOutputs:
+                cmdline.append(''.join([output, str(output_count)]))
+                output_count += 1
+            else:
+                cmdline.append(output)
+
+            cmdline.append(stdout_)
+            cmdline.append(stderr_)
+
+            yield ' '.join(cmdline)
+
+
+def get_tmp_filename(tmp_dir=gettempdir(), prefix="tmp", suffix=".txt",
+                     result_constructor=FilePath):
+    """ Generate a temporary filename and return as a FilePath object
+
+        tmp_dir: the directory to house the tmp_filename
+        prefix: string to append to beginning of filename
+            Note: It is very useful to have prefix be descriptive of the
+            process which is creating the temporary file. For example, if
+            your temp file will be used to build a temporary blast database,
+            you might pass prefix=TempBlastDB
+        suffix: the suffix to be appended to the temp filename
+        result_constructor: the constructor used to build the result filename
+            (default: cogent.app.parameters.FilePath). Note that joining
+            FilePath objects with one another or with strings, you must use
+            the + operator. If this causes trouble, you can pass str as the
+            the result_constructor.
+    """
+    # check not none
+    if not tmp_dir:
+        tmp_dir = ""
+    # if not current directory, append "/" if not already on path
+    elif not tmp_dir.endswith("/"):
+        tmp_dir += "/"
+
+    chars = "abcdefghigklmnopqrstuvwxyz"
+    picks = chars + chars.upper() + "0123456790"
+    return result_constructor(tmp_dir) + result_constructor(prefix) +\
+        result_constructor("%s%s" %
+                           (''.join([choice(picks) for i in range(20)]),
+                            suffix))
+
+
+def guess_input_handler(seqs, add_seq_names=False):
+    """Returns the name of the input handler for seqs."""
+    if isinstance(seqs, str):
+        if '\n' in seqs:  # can't be a filename...
+            return '_input_as_multiline_string'
+        else:  # assume it was a filename
+            return '_input_as_string'
+
+    if isinstance(seqs, list) and len(seqs) and isinstance(seqs[0], tuple):
+        return '_input_as_seq_id_seq_pairs'
+
+    if add_seq_names:
+        return '_input_as_seqs'
+
+    return '_input_as_lines'
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 5f426c8..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,18 +0,0 @@
-python-burrito (0.9.1-1) unstable; urgency=medium
-
-  * Initial upload to Debian (Closes: #793968)
-
- -- Andreas Tille <tille at debian.org>  Wed, 29 Jul 2015 15:40:04 +0200
-
-python-burrito (0.9.0-0biolinux3) trusty; urgency=medium
-
-  * Add missing build deps on dh_python, setuptools, nose
-
- -- Tim Booth <tbooth at ceh.ac.uk>  Mon, 02 Mar 2015 19:08:33 +0000
-
-python-burrito (0.9.0-0biolinux1) trusty; urgency=medium
-
-  * Initial release for QIIME 1.9
-  * Build for Python2 only just now.
-
- -- Tim Booth <tbooth at ceh.ac.uk>  Fri, 20 Feb 2015 18:10:56 +0000
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index 7401337..0000000
--- a/debian/control
+++ /dev/null
@@ -1,54 +0,0 @@
-Source: python-burrito
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Tim Booth <tbooth at ceh.ac.uk>,
-           Andreas Tille <tille at debian.org>
-Section: python
-Priority: optional
-Build-Depends: debhelper (>= 9),
-               python-all (>= 2.7),
-               dh-python,
-               python-future,
-               python-setuptools,
-               python-nose,
-               python3-all,
-               python3-future,
-               python3-setuptools,
-               python3-nose
-Standards-Version: 3.9.6
-Vcs-Browser: http://anonscm.debian.org/viewvc/debian-med/trunk/packages/python-burrito/trunk/
-Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/python-burrito/trunk/
-Homepage: https://github.com/biocore/burrito
-
-Package: python-burrito
-Architecture: all
-Depends: ${shlibs:Depends},
-         ${misc:Depends},
-         ${python:Depends}
-Description: Python 2 framework for wrapping and controlling command-line applications
- burrito, canonically pronounced boar-eee-toe, is a Python framework for
- wrapping and controlling command-line applications.
- .
- This tool allows developers to wrap command-line applications, just as burritos
- wrap delicious foods. Both hide the potentially unsightly details.
- .
- burrito is derived from the application controller framework code, which was
- originally added to PyCogent and later moved to scikit-bio.
- .
- This package provides the Python 2 modules.
-
-Package: python3-burrito
-Architecture: all
-Depends: ${shlibs:Depends},
-         ${misc:Depends},
-         ${python3:Depends}
-Description: Python 3 framework for wrapping and controlling command-line applications
- burrito, canonically pronounced boar-eee-toe, is a Python framework for
- wrapping and controlling command-line applications.
- .
- This tool allows developers to wrap command-line applications, just as burritos
- wrap delicious foods. Both hide the potentially unsightly details.
- .
- burrito is derived from the application controller framework code, which was
- originally added to PyCogent and later moved to scikit-bio.
- .
- This package provides the Python 3 modules.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index 2114ebe..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,40 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: burrito
-Upstream-Contact: gregcaporaso at gmail.com
-Source: https://github.com/biocore/burrito/
-
-Files: *
-Copyright: 2014-2015 burrito development team <gregcaporaso at gmail.com>
-License: BSD-3-clause
-
-Files: debian/*
-Copyright: 2015 Tim Booth <tbooth at ceh.ac.uk>
-                Andreas Tille <tille at debian.org>
-License: BSD-3-clause
-
-License: BSD-3-clause
- 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 names burrito or biocore 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/debian/patches/better_error_reporting b/debian/patches/better_error_reporting
deleted file mode 100644
index 00e5872..0000000
--- a/debian/patches/better_error_reporting
+++ /dev/null
@@ -1,24 +0,0 @@
-Author: Tim Booth <tbooth at ceh.ac.uk>
-Last-Update: Fri, 20 Feb 2015 18:10:56 +0000
-Description: More verbose error reporting
-
---- a/burrito/util.py
-+++ b/burrito/util.py
-@@ -297,10 +297,15 @@ class CommandLineApplication(Application
-             result = \
-                 CommandLineAppResult(out, err, exit_status,
-                                      result_paths=result_paths)
--        except ApplicationError:
--            result = \
-+        except ApplicationError as e1:
-+            try:
-+              result = \
-                 self._handle_app_result_build_failure(out, err, exit_status,
-                                                       result_paths)
-+            except ApplicationError:
-+                #If the handler just throws an error then report the first error,
-+                #not the new error.
-+                raise e1
- 
-         # Clean up the input file if one was created
-         if remove_tmp:
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 886711b..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-better_error_reporting
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index ca37898..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-export PYBUILD_NAME=burrito
-
-%:
-	dh $@ --with python2,python3 --buildsystem=pybuild
-
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index ac55a54..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=3
-https://pypi.python.org/pypi/burrito .*/burrito-([0-9.]+).tar.[xgb]z2?
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..861a9f5
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..8940668
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+
+# ----------------------------------------------------------------------------
+# Copyright (c) 2014--, burrito development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# ----------------------------------------------------------------------------
+
+from setuptools import find_packages, setup
+
+__version__ = "0.9.1"
+
+classes = """
+    Development Status :: 5 - Production/Stable
+    Intended Audience :: Developers
+    License :: OSI Approved :: BSD License
+    Topic :: Software Development :: Libraries
+    Topic :: Software Development :: Libraries :: Python Modules
+    Topic :: Utilities
+    Programming Language :: Python
+    Programming Language :: Python :: 2
+    Programming Language :: Python :: 2.7
+    Programming Language :: Python :: 3
+    Programming Language :: Python :: 3.3
+    Programming Language :: Python :: 3.4
+    Operating System :: Unix
+    Operating System :: POSIX
+    Operating System :: MacOS :: MacOS X
+"""
+classifiers = [s.strip() for s in classes.split('\n') if s]
+
+description = ('Framework for wrapping and controlling command-line '
+               'applications.')
+
+with open('README.rst') as f:
+    long_description = f.read()
+
+setup(name='burrito',
+      version=__version__,
+      license='BSD',
+      description=description,
+      long_description=long_description,
+      author="burrito development team",
+      author_email="gregcaporaso at gmail.com",
+      maintainer="burrito development team",
+      maintainer_email="gregcaporaso at gmail.com",
+      url='https://github.com/biocore/burrito',
+      test_suite='nose.collector',
+      packages=find_packages(),
+      install_requires=['future'],
+      extras_require={'test': ["nose >= 0.10.1", "flake8",
+                               "coveralls"]},
+      classifiers=classifiers)

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



More information about the debian-med-commit mailing list