Monday, June 28, 2010

A New Python Package: pyutilib.autotest

A while back I developed EXACT, a Python package for executing computational experiments using an XML-defined process. EXACT was designed to fill a particular niche in software testing: performing computational tests that involve the application of solvers to a suite of test problems. This sort of testing arises a lot when doing functionality testing for scientific software.

Unfortunately, EXACT was too complex:
  • The XML specification was complex and difficult to read
  • Experiments with many factors were assigned generic experiment IDs
  • It was hard to replication the execution of specific experiments
  • The experimental results were captured in XML results files that were difficult to browse
Even my close collaborators struggled to setup, run and analyze computational experiments! {sigh}

I have recently developed the pyutilib.autotest Python package to provide a simpler alternative to EXACT. This package uses a YAML test configuration file to specify the solvers and problems that are exercised in a test. The tests setup and executed with Python's unittest package, which allows the user to apply a rich set of testing methods. The user can specify a test driver in Python that defines how each test is executed, using the solver and problem options that are specified in the configuration file.

Here's a simple example of a YAML test specification, where the goal is to apply the UNIX cat command with different options to different test files:
driver: example

solvers:
cat:
cat2:
name: cat
cat_options: -n

problems:
f1:
file: file1.txt
f2:
file: file2.txt

suites:
suite1:
solvers:
cat:
cat2:
problems:
f1:
f2:
See the pyutilib.autotest PyPI documentation for further details.

Monday, June 21, 2010

Dynamic Service Creation in the PyUtilib Component Architecture

The PyUtilib Component Architecture (PCA) is a component architecture in Python that is derived from the Trac component framework. One important extension was to support both singleton and non-singleton plugins. Trac plugins are singletons that are created immediately when the plugin module is loaded (Python is a wonderful language for supporting this type of capability). Singleton plugins are well-suited for Trac, since it is a persistent application, but many other applications need to employ plugins "on demand". Consequently, the PCA supports non-singleton plugins, which need to be explicitly constructed by the end-user.

The PCA is widely used in the Coopr project, and most plugins are non-singletons. Until recently, the PCA did not directly support plugin construction on demand. That is, the user needed to know the plugin class name, and plugin construction was done explicitly by the user. However, most plugins in Coopr can be best described as named services. For example, Coopr optimizers are implemented as plugins and each optimizer has a unique name.

The PCA has recently been extended to support the alias function, which can be used to declare the name of a plugin with respect to a particular interface. For example, consider the following definitions of the MyPlugin and YourPlugin plugin classes:

class ITask(Interface):

def print(self):

class MyPlugin(Plugin):

implements(ITask)
alias('my', ITask)

def print(self):
print "My Plugin"

class YourPlugin(Plugin):

implements(ITask)
alias('your', ITask)

def print(self):
print "Your Plugin"

These plugins are non-singletons, so they are only registered and used if they are constructed. The alias function allows these plugins to be constructed with a factory class that is supported by the PCA. For example:

factory = CreatePluginFactory(ITask)

p1 = factory('my')
p2 = factory('your')

The CreatePluginFactory class is provided by the PCA, and it provides a functor that manages the creation of plugins whose names are registered with the alias function.

Blogs for Coopr and PyUtilib

This is just a heads-up that I have setup blogs for the Coopr and PyUtilib software projects:
These blogs will document releases and end-user advice and examples. Additionally, there will hopefully be other authors than just me adding content to these blogs. But, I guess we'll see.