Handle string args to CommandTask better

If a string is passed instead of an array, split on whitespace.

This makes things like t.run("sleep 5") actually work

Check-in a demo app to showcase the functionality as well
Move BaseTestCase, etc to sparts.tests.base
Add and improve some context helpers

- `ctx.chdir`: Temporarily `os.chdir(path)` to some new directory
- `ctx.snapshot_modules`: Clear module cache for new modules
  on context exit
- `ctx.add_path`: now has an optional `index` arg, that will cause
  it to use list.insert(`index`, ...) instead of list.append(...)
Add some new fileutils helpers, and a unittest

NamedTemporaryDirectory has been improved to:
- add `.symlink(path, dst)`, to symlink `dst` to the path inside the
  temporary directory.
- add `.path(relpath)`, to get the abspath `relpath` relative to
  `self.name`.  This removes a lot of `os.path.join()` calls
A wide variety of improvements to the thrift compiler wrapper

This is a partial rewrite of the compile context to support some future
planned features.  It also adds some basic unittests for this old and
new functioanlity.

- CompileContext.__init__(..., debug=False, ...).  Pass debug=True to
  persist any temporary files or directories.
- Use ctx.module_snapshot() to keep dynamically generated imports from
  polluting the global module cache
- Remove crazy dependency resolution, and crazy context manager bungling
  in favor of a more simple approach: compile the code with "-r" and without.
  The output dir generated with "-r" is added to the module path before
  generating the module.  The output dir generated without "-r" is used during
  the module generation traversal.
- CompileContext.makeTemporaryIncludeDir(): returns a NamedTemporaryDirectory
  containing symlinks to all explicit .thrift file and string dependencies.
- CompileContext.addIncludeDir(path): adds a -I `path` to thrift compiles.
- CompileContext.addDependentFilePath(path): if `path` is path/to/foo.thrift,
  symlinks to {tmpdir}/foo.thrift prior to compilation.
- CompileContext.addDependentFileContents(self, name, contents): saves
  `contents` to {tmpdir}/`name` prior to compilation.
- CompileContext.importThriftStr(contents): Let's you compile a raw string
  containing a thrift idl into a thrift module.