Matthew Turk avatar Matthew Turk committed 7ffc6f7

Major refactoring of the command-line parser to use argparse instead of cmdln.

* Everything is now a subclass of YTCommand
* Adding new commands is clearer and easier
* Uses argparse, a python 2.7 library
* We can use --config something=another with it
* Removed all of the pasteboard
* Moved a bunch of the yt source handling into yt/funcs.py
* Removed pexpect.py

Comments (0)

Files changed (4)

 
 class YTEmptyClass(object):
     pass
+
+def _update_hg(path, skip_rebuild = False):
+    from mercurial import hg, ui, commands
+    f = open(os.path.join(path, "yt_updater.log"), "a")
+    u = ui.ui()
+    u.pushbuffer()
+    config_fn = os.path.join(path, ".hg", "hgrc")
+    print "Reading configuration from ", config_fn
+    u.readconfig(config_fn)
+    repo = hg.repository(u, path)
+    commands.pull(u, repo)
+    f.write(u.popbuffer())
+    f.write("\n\n")
+    u.pushbuffer()
+    commands.identify(u, repo)
+    if "+" in u.popbuffer():
+        print "Can't rebuild modules by myself."
+        print "You will have to do this yourself.  Here's a sample commands:"
+        print
+        print "    $ cd %s" % (path)
+        print "    $ hg up"
+        print "    $ %s setup.py develop" % (sys.executable)
+        return 1
+    print "Updating the repository"
+    f.write("Updating the repository\n\n")
+    commands.update(u, repo, check=True)
+    if skip_rebuild: return
+    f.write("Rebuilding modules\n\n")
+    p = subprocess.Popen([sys.executable, "setup.py", "build_ext", "-i"], cwd=path,
+                        stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
+    stdout, stderr = p.communicate()
+    f.write(stdout)
+    f.write("\n\n")
+    if p.returncode:
+        print "BROKEN: See %s" % (os.path.join(path, "yt_updater.log"))
+        sys.exit(1)
+    f.write("Successful!\n")
+    print "Updated successfully."
+
+def _get_hg_version(path):
+    from mercurial import hg, ui, commands
+    u = ui.ui()
+    u.pushbuffer()
+    repo = hg.repository(u, path)
+    commands.identify(u, repo)
+    return u.popbuffer()
+
+def _get_yt_version():
+    import pkg_resources
+    yt_provider = pkg_resources.get_provider("yt")
+    path = os.path.dirname(yt_provider.module_path)
+    version = _get_hg_version(path)[:12]
+    return version
+
+# This code snippet is modified from Georg Brandl
+def _bb_apicall(endpoint, data, use_pass = True):
+    import urllib, urllib2
+    uri = 'https://api.bitbucket.org/1.0/%s/' % endpoint
+    # since bitbucket doesn't return the required WWW-Authenticate header when
+    # making a request without Authorization, we cannot use the standard urllib2
+    # auth handlers; we have to add the requisite header from the start
+    if data is not None:
+        data = urllib.urlencode(data)
+    req = urllib2.Request(uri, data)
+    if use_pass:
+        username = raw_input("Bitbucket Username? ")
+        password = getpass.getpass()
+        upw = '%s:%s' % (username, password)
+        req.add_header('Authorization', 'Basic %s' % base64.b64encode(upw).strip())
+    return urllib2.urlopen(req).read()
+
+def _get_yt_supp():
+    supp_path = os.path.join(os.environ["YT_DEST"], "src",
+                             "yt-supplemental")
+    # Now we check that the supplemental repository is checked out.
+    if not os.path.isdir(supp_path):
+        print
+        print "*** The yt-supplemental repository is not checked ***"
+        print "*** out.  I can do this for you, but because this ***"
+        print "*** is a delicate act, I require you to respond   ***"
+        print "*** to the prompt with the word 'yes'.            ***"
+        print
+        response = raw_input("Do you want me to try to check it out? ")
+        if response != "yes":
+            print
+            print "Okay, I understand.  You can check it out yourself."
+            print "This command will do it:"
+            print
+            print "$ hg clone http://hg.yt-project.org/yt-supplemental/ ",
+            print "%s" % (supp_path)
+            print
+            sys.exit(1)
+        rv = commands.clone(uu,
+                "http://hg.yt-project.org/yt-supplemental/", supp_path)
+        if rv:
+            print "Something has gone wrong.  Quitting."
+            sys.exit(1)
+    # Now we think we have our supplemental repository.
+    return supp_path
+

yt/utilities/command_line.py

 
 from yt.config import ytcfg
 ytcfg["yt","__command_line"] = "True"
+from yt.startup_tasks import parser
 from yt.mods import *
 from yt.funcs import *
-import cmdln as cmdln
-import optparse, os, os.path, math, sys, time, subprocess, getpass, tempfile
+import argparse, os, os.path, math, sys, time, subprocess, getpass, tempfile
 import urllib, urllib2, base64
 
 def _fix_pf(arg):
         pf = load(arg[:-10])
     else:
         pf = load(arg)
-    if pf is None:
-        raise IOError
     return pf
 
+subparsers = parser.add_subparsers(title="subcommands",
+                    description="Valid subcommands",)
+
+def _add_arg(sc, arg):
+    if isinstance(arg, types.StringTypes):
+        arg = _common_options[arg].copy()
+    argnames = []
+    if "short" in arg: argnames.append(arg.pop('short'))
+    if "long" in arg: argnames.append(arg.pop('long'))
+    sc.add_argument(*argnames, **arg)
+
+class YTCommand(object):
+    args = ()
+    name = None
+    description = ""
+    aliases = ()
+    npfs = 1
+
+    class __metaclass__(type):
+        def __init__(cls, name, b, d):
+            type.__init__(cls, name, b, d)
+            if cls.name is not None:
+                print "Adding", cls.name
+                sc = subparsers.add_parser(cls.name,
+                    description = cls.description)
+                sc.set_defaults(func=cls.run)
+                for arg in cls.args:
+                    _add_arg(sc, arg)
+
+    @classmethod
+    def run(cls, args):
+        self = cls()
+        # Some commands need to be run repeatedly on parameter files
+        # In fact, this is the rule and the opposite is the exception
+        # BUT, we only want to parse the arguments once.
+        if cls.npfs > 1:
+            self(args)
+        else:
+            if len(getattr(args, "pf", [])) > 1:
+                pfs = args.pf
+                for pf in pfs:
+                    args.pf = pf
+                    self(args)
+            else:
+                args.pf = args.pf[0]
+                self(args)
+
+class GetParameterFiles(argparse.Action):
+    def __call__(self, parser, namespace, values, option_string = None):
+        if len(values) == 1:
+            pfs = values
+        elif len(values) == 2 and namespace.basename is not None:
+            pfs = ["%s%04i" % (opts.basename, r)
+                   for r in range(int(values[0]), int(values[1]), opts.skip) ]
+        else:
+            pfs = values
+        namespace.pf = [_fix_pf(pf) for pf in pfs]
+
 _common_options = dict(
+    pf      = dict(short="pf", action=GetParameterFiles,
+                   nargs="+", help="Parameter files to run on"),
     axis    = dict(short="-a", long="--axis",
-                   action="store", type="int",
+                   action="store", type=int,
                    dest="axis", default=4,
                    help="Axis (4 for all three)"),
     log     = dict(short="-l", long="--log",
                    dest="takelog", default=True,
                    help="Take the log of the field?"),
     text    = dict(short="-t", long="--text",
-                   action="store", type="string",
+                   action="store", type=str,
                    dest="text", default=None,
                    help="Textual annotation"),
     field   = dict(short="-f", long="--field",
-                   action="store", type="string",
+                   action="store", type=str,
                    dest="field", default="Density",
                    help="Field to color by"),
     weight  = dict(short="-g", long="--weight",
-                   action="store", type="string",
+                   action="store", type=str,
                    dest="weight", default=None,
                    help="Field to weight projections with"),
-    cmap    = dict(short="", long="--colormap",
-                   action="store", type="string",
+    cmap    = dict(long="--colormap",
+                   action="store", type=str,
                    dest="cmap", default="jet",
                    help="Colormap name"),
     zlim    = dict(short="-z", long="--zlim",
-                   action="store", type="float",
+                   action="store", type=float,
                    dest="zlim", default=None,
                    nargs=2,
                    help="Color limits (min, max)"),
-    dex     = dict(short="", long="--dex",
-                   action="store", type="float",
+    dex     = dict(long="--dex",
+                   action="store", type=float,
                    dest="dex", default=None,
                    nargs=1,
                    help="Number of dex above min to display"),
     width   = dict(short="-w", long="--width",
-                   action="store", type="float",
+                   action="store", type=float,
                    dest="width", default=1.0,
                    help="Width in specified units"),
     unit    = dict(short="-u", long="--unit",
-                   action="store", type="string",
+                   action="store", type=str,
                    dest="unit", default='unitary',
                    help="Desired units"),
     center  = dict(short="-c", long="--center",
-                   action="store", type="float",
+                   action="store", type=float,
                    dest="center", default=None,
                    nargs=3,
                    help="Center, space separated (-1 -1 -1 for max)"),
     bn      = dict(short="-b", long="--basename",
-                   action="store", type="string",
+                   action="store", type=str,
                    dest="basename", default=None,
                    help="Basename of parameter files"),
     output  = dict(short="-o", long="--output",
-                   action="store", type="string",
+                   action="store", type=str,
                    dest="output", default="frames/",
                    help="Folder in which to place output images"),
     outputfn= dict(short="-o", long="--output",
-                   action="store", type="string",
+                   action="store", type=str,
                    dest="output", default=None,
                    help="File in which to place output"),
     skip    = dict(short="-s", long="--skip",
-                   action="store", type="int",
+                   action="store", type=int,
                    dest="skip", default=1,
                    help="Skip factor for outputs"),
     proj    = dict(short="-p", long="--projection",
                    action="store_true", 
                    dest="projection", default=False,
                    help="Use a projection rather than a slice"),
-    maxw    = dict(short="", long="--max-width",
-                   action="store", type="float",
+    maxw    = dict(long="--max-width",
+                   action="store", type=float,
                    dest="max_width", default=1.0,
                    help="Maximum width in code units"),
-    minw    = dict(short="", long="--min-width",
-                   action="store", type="float",
+    minw    = dict(long="--min-width",
+                   action="store", type=float,
                    dest="min_width", default=50,
                    help="Minimum width in units of smallest dx (default: 50)"),
     nframes = dict(short="-n", long="--nframes",
-                   action="store", type="int",
+                   action="store", type=int,
                    dest="nframes", default=100,
                    help="Number of frames to generate"),
-    slabw   = dict(short="", long="--slab-width",
-                   action="store", type="float",
+    slabw   = dict(long="--slab-width",
+                   action="store", type=float,
                    dest="slab_width", default=1.0,
                    help="Slab width in specified units"),
     slabu   = dict(short="-g", long="--slab-unit",
-                   action="store", type="string",
+                   action="store", type=str,
                    dest="slab_unit", default='1',
                    help="Desired units for the slab"),
-    ptype   = dict(short="", long="--particle-type",
-                   action="store", type="int",
+    ptype   = dict(long="--particle-type",
+                   action="store", type=int,
                    dest="ptype", default=2,
                    help="Particle type to select"),
-    agecut  = dict(short="", long="--age-cut",
-                   action="store", type="float",
+    agecut  = dict(long="--age-cut",
+                   action="store", type=float,
                    dest="age_filter", default=None,
                    nargs=2,
                    help="Bounds for the field to select"),
-    uboxes  = dict(short="", long="--unit-boxes",
+    uboxes  = dict(long="--unit-boxes",
                    action="store_true",
                    dest="unit_boxes",
                    help="Display helpful unit boxes"),
-    thresh  = dict(short="", long="--threshold",
-                   action="store", type="float",
+    thresh  = dict(long="--threshold",
+                   action="store", type=float,
                    dest="threshold", default=None,
                    help="Density threshold"),
-    dm_only = dict(short="", long="--all-particles",
+    dm_only = dict(long="--all-particles",
                    action="store_false", 
                    dest="dm_only", default=True,
                    help="Use all particles"),
-    grids   = dict(short="", long="--show-grids",
+    grids   = dict(long="--show-grids",
                    action="store_true",
                    dest="grids", default=False,
                    help="Show the grid boundaries"),
-    time    = dict(short="", long="--time",
+    time    = dict(long="--time",
                    action="store_true",
                    dest="time", default=False,
                    help="Print time in years on image"),
-    contours    = dict(short="", long="--contours",
-                   action="store",type="int",
+    contours    = dict(long="--contours",
+                   action="store",type=int,
                    dest="contours", default=None,
                    help="Number of Contours for Rendering"),
-    contour_width  = dict(short="", long="--contour_width",
-                   action="store",type="float",
+    contour_width  = dict(long="--contour_width",
+                   action="store",type=float,
                    dest="contour_width", default=None,
                    help="Width of gaussians used for rendering."),
-    enhance   = dict(short="", long="--enhance",
+    enhance   = dict(long="--enhance",
                    action="store_true",
                    dest="enhance", default=False,
                    help="Enhance!"),
     valrange  = dict(short="-r", long="--range",
-                   action="store", type="float",
+                   action="store", type=float,
                    dest="valrange", default=None,
                    nargs=2,
                    help="Range, space separated"),
-    up  = dict(short="", long="--up",
-                   action="store", type="float",
+    up  = dict(long="--up",
+                   action="store", type=float,
                    dest="up", default=None,
                    nargs=3,
                    help="Up, space separated"),
-    viewpoint  = dict(short="", long="--viewpoint",
-                   action="store", type="float",
+    viewpoint  = dict(long="--viewpoint",
+                   action="store", type=float,
                    dest="viewpoint", default=[1., 1., 1.],
                    nargs=3,
                    help="Viewpoint, space separated"),
-    pixels    = dict(short="", long="--pixels",
-                   action="store",type="int",
+    pixels    = dict(long="--pixels",
+                   action="store",type=int,
                    dest="pixels", default=None,
                    help="Number of Pixels for Rendering"),
-    halos   = dict(short="", long="--halos",
-                   action="store", type="string",
+    halos   = dict(long="--halos",
+                   action="store", type=str,
                    dest="halos",default="multiple",
                    help="Run halo profiler on a 'single' halo or 'multiple' halos."),
-    halo_radius = dict(short="", long="--halo_radius",
-                       action="store", type="float",
+    halo_radius = dict(long="--halo_radius",
+                       action="store", type=float,
                        dest="halo_radius",default=0.1,
                        help="Constant radius for profiling halos if using hop output files with no radius entry. Default: 0.1."),
-    halo_radius_units = dict(short="", long="--halo_radius_units",
-                             action="store", type="string",
+    halo_radius_units = dict(long="--halo_radius_units",
+                             action="store", type=str,
                              dest="halo_radius_units",default="1",
                              help="Units for radius used with --halo_radius flag. Default: '1' (code units)."),
-    halo_hop_style = dict(short="", long="--halo_hop_style",
-                          action="store", type="string",
+    halo_hop_style = dict(long="--halo_hop_style",
+                          action="store", type=str,
                           dest="halo_hop_style",default="new",
                           help="Style of hop output file.  'new' for yt_hop files and 'old' for enzo_hop files."),
-    halo_parameter_file = dict(short="", long="--halo_parameter_file",
-                               action="store", type="string",
+    halo_parameter_file = dict(long="--halo_parameter_file",
+                               action="store", type=str,
                                dest="halo_parameter_file",default=None,
                                help="HaloProfiler parameter file."),
-    make_profiles = dict(short="", long="--make_profiles",
+    make_profiles = dict(long="--make_profiles",
                          action="store_true", default=False,
                          help="Make profiles with halo profiler."),
-    make_projections = dict(short="", long="--make_projections",
+    make_projections = dict(long="--make_projections",
                             action="store_true", default=False,
                             help="Make projections with halo profiler.")
 
     )
 
-def _add_options(parser, *options):
-    for opt in options:
-        oo = _common_options[opt].copy()
-        parser.add_option(oo.pop("short"), oo.pop("long"), **oo)
 
-def _get_parser(*options):
-    parser = optparse.OptionParser()
-    _add_options(parser, *options)
-    return parser
-
-def add_cmd_options(options):
-    opts = []
-    for option in options:
-        vals = _common_options[option].copy()
-        opts.append(([vals.pop("short"), vals.pop("long")],
-                      vals))
-    def apply_options(func):
-        for args, kwargs in opts:
-            func = cmdln.option(*args, **kwargs)(func)
-        return func
-    return apply_options
-
-def check_args(func):
-    @wraps(func)
-    def arg_iterate(self, subcmd, opts, *args):
-        if len(args) == 1:
-            pfs = args
-        elif len(args) == 2 and opts.basename is not None:
-            pfs = ["%s%04i" % (opts.basename, r)
-                   for r in range(int(args[0]), int(args[1]), opts.skip) ]
-        else: pfs = args
-        for arg in pfs:
-            func(self, subcmd, opts, arg)
-    return arg_iterate
-
-def _update_hg(path, skip_rebuild = False):
-    from mercurial import hg, ui, commands
-    f = open(os.path.join(path, "yt_updater.log"), "a")
-    u = ui.ui()
-    u.pushbuffer()
-    config_fn = os.path.join(path, ".hg", "hgrc")
-    print "Reading configuration from ", config_fn
-    u.readconfig(config_fn)
-    repo = hg.repository(u, path)
-    commands.pull(u, repo)
-    f.write(u.popbuffer())
-    f.write("\n\n")
-    u.pushbuffer()
-    commands.identify(u, repo)
-    if "+" in u.popbuffer():
-        print "Can't rebuild modules by myself."
-        print "You will have to do this yourself.  Here's a sample commands:"
-        print
-        print "    $ cd %s" % (path)
-        print "    $ hg up"
-        print "    $ %s setup.py develop" % (sys.executable)
-        return 1
-    print "Updating the repository"
-    f.write("Updating the repository\n\n")
-    commands.update(u, repo, check=True)
-    if skip_rebuild: return
-    f.write("Rebuilding modules\n\n")
-    p = subprocess.Popen([sys.executable, "setup.py", "build_ext", "-i"], cwd=path,
-                        stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
-    stdout, stderr = p.communicate()
-    f.write(stdout)
-    f.write("\n\n")
-    if p.returncode:
-        print "BROKEN: See %s" % (os.path.join(path, "yt_updater.log"))
-        sys.exit(1)
-    f.write("Successful!\n")
-    print "Updated successfully."
-
-def _get_hg_version(path):
-    from mercurial import hg, ui, commands
-    u = ui.ui()
-    u.pushbuffer()
-    repo = hg.repository(u, path)
-    commands.identify(u, repo)
-    return u.popbuffer()
-
-def get_yt_version():
-    import pkg_resources
-    yt_provider = pkg_resources.get_provider("yt")
-    path = os.path.dirname(yt_provider.module_path)
-    version = _get_hg_version(path)[:12]
-    return version
-
-# This code snippet is modified from Georg Brandl
-def bb_apicall(endpoint, data, use_pass = True):
-    uri = 'https://api.bitbucket.org/1.0/%s/' % endpoint
-    # since bitbucket doesn't return the required WWW-Authenticate header when
-    # making a request without Authorization, we cannot use the standard urllib2
-    # auth handlers; we have to add the requisite header from the start
-    if data is not None:
-        data = urllib.urlencode(data)
-    req = urllib2.Request(uri, data)
-    if use_pass:
-        username = raw_input("Bitbucket Username? ")
-        password = getpass.getpass()
-        upw = '%s:%s' % (username, password)
-        req.add_header('Authorization', 'Basic %s' % base64.b64encode(upw).strip())
-    return urllib2.urlopen(req).read()
-
-def _get_yt_supp():
-    supp_path = os.path.join(os.environ["YT_DEST"], "src",
-                             "yt-supplemental")
-    # Now we check that the supplemental repository is checked out.
-    if not os.path.isdir(supp_path):
-        print
-        print "*** The yt-supplemental repository is not checked ***"
-        print "*** out.  I can do this for you, but because this ***"
-        print "*** is a delicate act, I require you to respond   ***"
-        print "*** to the prompt with the word 'yes'.            ***"
-        print
-        response = raw_input("Do you want me to try to check it out? ")
-        if response != "yes":
-            print
-            print "Okay, I understand.  You can check it out yourself."
-            print "This command will do it:"
-            print
-            print "$ hg clone http://hg.yt-project.org/yt-supplemental/ ",
-            print "%s" % (supp_path)
-            print
-            sys.exit(1)
-        rv = commands.clone(uu,
-                "http://hg.yt-project.org/yt-supplemental/", supp_path)
-        if rv:
-            print "Something has gone wrong.  Quitting."
-            sys.exit(1)
-    # Now we think we have our supplemental repository.
-    return supp_path
-
-class YTCommands(cmdln.Cmdln):
-    name="yt"
-
-    def __init__(self, *args, **kwargs):
-        cmdln.Cmdln.__init__(self, *args, **kwargs)
-        cmdln.Cmdln.do_help.aliases.append("h")
-
-    def do_update(self, subcmd, opts):
+class YTUpdateCmd(YTCommand):
+    name = "update"
+    description = \
         """
         Update the yt installation to the most recent version
 
-        ${cmd_usage}
-        ${cmd_option_list}
         """
+
+    def __call__(self, opts):
         import pkg_resources
         yt_provider = pkg_resources.get_provider("yt")
         path = os.path.dirname(yt_provider.module_path)
             print "updating to the newest changeset."
             print
 
-    @cmdln.option("-u", "--update-source", action="store_true",
-                  default = False,
-                  help="Update the yt installation, if able")
-    @cmdln.option("-o", "--output-version", action="store",
+class YTInstInfoCmd(YTCommand):
+    name = "instinfo"
+    args = (
+            dict(short="-u", long="--update-source", action="store_true",
+                 default = False,
+                 help="Update the yt installation, if able"),
+            dict(short="-o", long="--output-version", action="store",
                   default = None, dest="outputfile",
-                  help="File into which the current revision number will be stored")
-    def do_instinfo(self, subcmd, opts):
+                  help="File into which the current revision number will be" +
+                       "stored")
+           )
+    description = \
         """
         Get some information about the yt installation
 
-        ${cmd_usage}
-        ${cmd_option_list}
         """
+
+    def __call__(self, opts):
         import pkg_resources
         yt_provider = pkg_resources.get_provider("yt")
         path = os.path.dirname(yt_provider.module_path)
         if vstring is not None and opts.outputfile is not None:
             open(opts.outputfile, "w").write(vstring)
 
-    def do_load(self, subcmd, opts, arg):
+class YTLoadCmd(YTCommand):
+    name = "load"
+    description = \
         """
         Load a single dataset into an IPython instance
 
-        ${cmd_option_list}
         """
-        try:
-            pf = _fix_pf(arg)
-        except IOError:
+
+    args = ("pf", )
+
+    def __call__(self, args):
+        if args.pf is None:
             print "Could not load file."
             sys.exit()
         import yt.mods
             from IPython.frontend.terminal.embed import InteractiveShellEmbed
             ipshell = InteractiveShellEmbed(config=cfg)
 
-    @add_cmd_options(['outputfn','bn','thresh','dm_only','skip'])
-    @check_args
-    def do_hop(self, subcmd, opts, arg):
+class YTHopCmd(YTCommand):
+    args = ('outputfn','bn','thresh','dm_only','skip', 'pf')
+    name = "hop"
+    description = \
         """
         Run HOP on one or more datasets
 
-        ${cmd_option_list}
         """
-        pf = _fix_pf(arg)
-        kwargs = {'dm_only' : opts.dm_only}
-        if opts.threshold is not None: kwargs['threshold'] = opts.threshold
+
+    def __call__(self, args):
+        pf = args.pf
+        kwargs = {'dm_only' : args.dm_only}
+        if args.threshold is not None: kwargs['threshold'] = args.threshold
         hop_list = HaloFinder(pf, **kwargs)
-        if opts.output is None: fn = "%s.hop" % pf
-        else: fn = opts.output
+        if args.output is None: fn = "%s.hop" % pf
+        else: fn = args.output
         hop_list.write_out(fn)
 
-    @add_cmd_options(['make_profiles','make_projections','halo_parameter_file',
-                      'halos','halo_hop_style','halo_radius','halo_radius_units'])
-    def do_halos(self, subcmd, opts, arg):
+class YTHalosCmd(YTCommand):
+    name = "halos"
+    args = ('make_profiles','make_projections','halo_parameter_file',
+            'halos','halo_hop_style','halo_radius','halo_radius_units', 'pf')
+    description = \
         """
         Run HaloProfiler on one dataset
 
-        ${cmd_option_list}
         """
+    def __call__(self, args):
         import yt.analysis_modules.halo_profiler.api as HP
-        kwargs = {'halos': opts.halos,
-                  'halo_radius': opts.halo_radius,
-                  'radius_units': opts.halo_radius_units}
+        kwargs = {'halos': args.halos,
+                  'halo_radius': args.halo_radius,
+                  'radius_units': args.halo_radius_units}
 
-        hp = HP.HaloProfiler(arg,opts.halo_parameter_file,**kwargs)
-        if opts.make_profiles:
+        hp = HP.HaloProfiler(arg,args.halo_parameter_file,**kwargs)
+        if args.make_profiles:
             hp.make_profiles()
-        if opts.make_projections:
+        if args.make_projections:
             hp.make_projections()
 
-    @add_cmd_options(["width", "unit", "bn", "proj", "center",
-                      "zlim", "axis", "field", "weight", "skip",
-                      "cmap", "output", "grids", "time"])
-    @check_args
-    def do_plot(self, subcmd, opts, arg):
+class YTPlotCmd(YTCommand):
+    args = ("width", "unit", "bn", "proj", "center",
+            "zlim", "axis", "field", "weight", "skip",
+            "cmap", "output", "grids", "time", "pf")
+    name = "plot"
+    
+    description = \
         """
         Create a set of images
 
-        ${cmd_usage}
-        ${cmd_option_list}
         """
-        pf = _fix_pf(arg)
-        center = opts.center
-        if opts.center == (-1,-1,-1):
+
+    def __call__(self, args):
+        pf = args.pf
+        center = args.center
+        if args.center == (-1,-1,-1):
             mylog.info("No center fed in; seeking.")
             v, center = pf.h.find_max("Density")
-        elif opts.center is None:
+        elif args.center is None:
             center = 0.5*(pf.domain_left_edge + pf.domain_right_edge)
         center = na.array(center)
         pc=PlotCollection(pf, center=center)
-        if opts.axis == 4:
+        if args.axis == 4:
             axes = range(3)
         else:
-            axes = [opts.axis]
+            axes = [args.axis]
         for ax in axes:
             mylog.info("Adding plot for axis %i", ax)
-            if opts.projection: pc.add_projection(opts.field, ax,
-                                    weight_field=opts.weight, center=center)
-            else: pc.add_slice(opts.field, ax, center=center)
-            if opts.grids: pc.plots[-1].modify["grids"]()
-            if opts.time: 
+            if args.projection: pc.add_projection(args.field, ax,
+                                    weight_field=args.weight, center=center)
+            else: pc.add_slice(args.field, ax, center=center)
+            if args.grids: pc.plots[-1].modify["grids"]()
+            if args.time: 
                 time = pf.current_time*pf['Time']*pf['years']
                 pc.plots[-1].modify["text"]((0.2,0.8), 't = %5.2e yr'%time)
-        pc.set_width(opts.width, opts.unit)
-        pc.set_cmap(opts.cmap)
-        if opts.zlim: pc.set_zlim(*opts.zlim)
-        if not os.path.isdir(opts.output): os.makedirs(opts.output)
-        pc.save(os.path.join(opts.output,"%s" % (pf)))
+        pc.set_width(args.width, args.unit)
+        pc.set_cmap(args.cmap)
+        if args.zlim: pc.set_zlim(*args.zlim)
+        if not os.path.isdir(args.output): os.makedirs(args.output)
+        pc.save(os.path.join(args.output,"%s" % (pf)))
 
-    @add_cmd_options(["proj", "field", "weight"])
-    @cmdln.option("-a", "--axis", action="store", type="int",
-                   dest="axis", default=0, help="Axis (4 for all three)")
-    @cmdln.option("-o", "--host", action="store", type="string",
+class YTMapserverCmd(YTCommand):
+    args = ("proj", "field", "weight",
+            dict(short="-a", long="--axis", action="store", type=int,
+                 dest="axis", default=0, help="Axis (4 for all three)"),
+            dict(short ="-o", long="--host", action="store", type=str,
                    dest="host", default=None, help="IP Address to bind on")
-    @check_args
-    def do_mapserver(self, subcmd, opts, arg):
+            )
+    
+    name = "mapserver"
+    description = \
         """
         Serve a plot in a GMaps-style interface
 
-        ${cmd_usage}
-        ${cmd_option_list}
         """
-        pf = _fix_pf(arg)
+
+    def __call__(self, args):
+        pf = args.pf
         pc=PlotCollection(pf, center=0.5*(pf.domain_left_edge +
                                           pf.domain_right_edge))
-        if opts.axis == 4:
+        if args.axis == 4:
             print "Doesn't work with multiple axes!"
             return
-        if opts.projection:
-            p = pc.add_projection(opts.field, opts.axis, weight_field=opts.weight)
+        if args.projection:
+            p = pc.add_projection(args.field, args.axis, weight_field=args.weight)
         else:
-            p = pc.add_slice(opts.field, opts.axis)
+            p = pc.add_slice(args.field, args.axis)
         from yt.gui.reason.pannable_map import PannableMapServer
-        mapper = PannableMapServer(p.data, opts.field)
+        mapper = PannableMapServer(p.data, args.field)
         import yt.utilities.bottle as bottle
         bottle.debug(True)
-        if opts.host is not None:
-            colonpl = opts.host.find(":")
+        if args.host is not None:
+            colonpl = args.host.find(":")
             if colonpl >= 0:
-                port = int(opts.host.split(":")[-1])
-                opts.host = opts.host[:colonpl]
+                port = int(args.host.split(":")[-1])
+                args.host = args.host[:colonpl]
             else:
                 port = 8080
-            bottle.run(server='rocket', host=opts.host, port=port)
+            bottle.run(server='rocket', host=args.host, port=port)
         else:
             bottle.run(server='rocket')
 
-    def do_rpdb(self, subcmd, opts, task):
+class YTRPDBCmd(YTCommand):
+    name = "rpdb"
+    description = \
         """
         Connect to a currently running (on localhost) rpd session.
 
         Commands run with --rpdb will trigger an rpdb session with any
         uncaught exceptions.
 
-        ${cmd_usage} 
-        ${cmd_option_list}
         """
+
+    def __call__(self, args):
         import rpdb
         rpdb.run_rpdb(int(task))
 
-    @add_cmd_options(['outputfn','bn','skip'])
-    @check_args
-    def do_stats(self, subcmd, opts, arg):
+class YTStatsCmd(YTCommand):
+    args = ('outputfn','bn','skip','pf')
+    name = "stats"
+    description = \
         """
         Print stats and maximum density for one or more datasets
 
-        ${cmd_option_list}
         """
-        pf = _fix_pf(arg)
+
+    def __call__(self, args):
+        pf = args.pf
         pf.h.print_stats()
         if "Density" in pf.h.field_list:
             v, c = pf.h.find_max("Density")
         print "Maximum density: %0.5e at %s" % (v, c)
-        if opts.output is not None:
+        if args.output is not None:
             t = pf.current_time * pf['years']
-            open(opts.output, "a").write(
+            open(args.output, "a").write(
                 "%s (%0.5e years): %0.5e at %s\n" % (pf, t, v, c))
 
-    @add_cmd_options([])
-    def _do_analyze(self, subcmd, opts, arg):
+class YTAnalyzeCmd(YTCommand):
+    
+    name = "analyze"
+    args = ('pf',)
+    description = \
         """
         Produce a set of analysis for a given output.  This includes
         HaloProfiler results with r200, as per the recipe file in the cookbook,
         profiles of a number of fields, projections of average Density and
         Temperature, and distribution functions for Density and Temperature.
 
-        ${cmd_option_list}
         """
+
+    def __call__(self, args):
         # We will do the following things:
         #   Halo profiling (default parameters ONLY)
         #   Projections: Density, Temperature
         ph.modify["line"](pr.field_data["Density"], pr.field_data["Temperature"])
         pc.save()
 
-    @cmdln.option("-d", "--desc", action="store",
-                  default = None, dest="desc",
-                  help="Description for this pasteboard entry")
-    def do_pasteboard(self, subcmd, opts, arg):
-        """
-        Place a file into your pasteboard.
-        """
-        if opts.desc is None: raise RuntimeError
-        from yt.utilities.pasteboard import PostInventory
-        pp = PostInventory()
-        pp.add_post(arg, desc=opts.desc)
-
-    @cmdln.option("-l", "--language", action="store",
+class YTPastebinCmd(YTCommand):
+    name = "pastebin"
+    args = (
+             dict(short="-l", long="--language", action="store",
                   default = None, dest="language",
-                  help="Use syntax highlighter for the file in language")
-    @cmdln.option("-L", "--languages", action="store_true",
+                  help="Use syntax highlighter for the file in language"),
+             dict(short="-L", long="--languages", action="store_true",
                   default = False, dest="languages",
-                  help="Retrive a list of supported languages")
-    @cmdln.option("-e", "--encoding", action="store",
+                  help="Retrive a list of supported languages"),
+             dict(short="-e", long="--encoding", action="store",
                   default = 'utf-8', dest="encoding",
                   help="Specify the encoding of a file (default is "
-                        "utf-8 or guessing if available)")
-    @cmdln.option("-b", "--open-browser", action="store_true",
+                        "utf-8 or guessing if available)"),
+             dict(short="-b", long="--open-browser", action="store_true",
                   default = False, dest="open_browser",
-                  help="Open the paste in a web browser")
-    @cmdln.option("-p", "--private", action="store_true",
+                  help="Open the paste in a web browser"),
+             dict(short="-p", long="--private", action="store_true",
                   default = False, dest="private",
-                  help="Paste as private")
-    @cmdln.option("-c", "--clipboard", action="store_true",
+                  help="Paste as private"),
+             dict(short="-c", long="--clipboard", action="store_true",
                   default = False, dest="clipboard",
-                  help="File to output to; else, print.")
-    def do_pastebin(self, subcmd, opts, arg):
+                  help="File to output to; else, print."),
+             dict(short="file", type=str),
+            )
+    description = \
         """
         Post a script to an anonymous pastebin
 
         Usage: yt pastebin [options] <script>
 
-        ${cmd_option_list}
         """
+
+    def __call__(self, args):
         import yt.utilities.lodgeit as lo
-        lo.main( arg, languages=opts.languages, language=opts.language,
-                 encoding=opts.encoding, open_browser=opts.open_browser,
-                 private=opts.private, clipboard=opts.clipboard)
+        lo.main(args.file, languages=args.languages, language=args.language,
+                 encoding=args.encoding, open_browser=args.open_browser,
+                 private=args.private, clipboard=args.clipboard)
 
-    def do_pastebin_grab(self, subcmd, opts, arg):
+class YTPastebinGrabCmd(YTCommand):
+    args = (dict(short="number", type=str),)
+    name = "pastebin_grab"
+    description = \
         """
         Print an online pastebin to STDOUT for local use. Paste ID is 
         the number at the end of the url.  So to locally access pastebin:
         Ex: yt pastebin_grab 1688 > script.py
 
         """
+
+    def __call__(self, args):
         import yt.utilities.lodgeit as lo
-        lo.main( None, download=arg )
+        lo.main( None, download=args.number )
 
-    @cmdln.option("-o", "--output", action="store",
-                  default = None, dest="output_fn",
-                  help="File to output to; else, print.")
-    def do_pasteboard_grab(self, subcmd, opts, username, paste_id):
-        """
-        Download from your or another user's pasteboard
 
-        ${cmd_usage} 
-        ${cmd_option_list}
-        """
-        from yt.utilities.pasteboard import retrieve_pastefile
-        retrieve_pastefile(username, paste_id, opts.output_fn)
-
-    def do_bugreport(self, subcmd, opts):
+class YTBugreportCmd(YTCommand):
+    name = "bureport"
+    description = \
         """
         Report a bug in yt
 
-        ${cmd_usage} 
-        ${cmd_option_list}
         """
+
+    def __call__(self, args):
         print "==============================================================="
         print
         print "Hi there!  Welcome to the yt bugreport taker."
         print "projections')"
         print
         try:
-            current_version = get_yt_version()
+            current_version = _get_yt_version()
         except:
             current_version = "Unavailable"
         summary = raw_input("Summary? ")
         print "If you don't have one, run the 'yt bootstrap_dev' command."
         print
         loki = raw_input()
-        retval = bb_apicall(endpoint, data, use_pass=True)
+        retval = _bb_apicall(endpoint, data, use_pass=True)
         import json
         retval = json.loads(retval)
         url = "http://hg.yt-project.org/yt/issue/%s" % retval['local_id']
         print "Keep in touch!"
         print
 
-    def do_bootstrap_dev(self, subcmd, opts):
+class YTBootstrapDevCmd(YTCommand):
+    name = "bootstrap_dev"
+    description = \
         """
         Bootstrap a yt development environment
-
-        ${cmd_usage} 
-        ${cmd_option_list}
         """
+    def __call__(self, args):
         from mercurial import hg, ui, commands
         import imp
         import getpass
         print "Hi there!  Welcome to the yt development bootstrap tool."
         print
         print "This should get you started with mercurial as well as a few"
-        print "other handy things, like a pasteboard of your very own."
+        print "other handy things"
         print
         # We have to do a couple things.
         # First, we check that YT_DEST is set.
         print " 1. Setting up your ~/.hgrc to have a username."
         print " 2. Setting up your bitbucket user account and the hgbb"
         print "    extension."
-        print " 3. Setting up a new pasteboard repository."
         print
         firstname = lastname = email_address = bbusername = repo_list = None
         # Now we try to import the cedit extension.
         # We now reload the UI's config file so that it catches the [bb]
         # section changes.
         uu.readconfig(hgrc_path[0])
-        # Now the only thing remaining to do is to set up the pasteboard
-        # repository.
-        # This is, unfortunately, the most difficult.
-        print
-        print "We are now going to set up a pasteboard. This is a mechanism"
-        print "for versioned posting of snippets, collaboration and"
-        print "discussion."
-        print
-        # Let's get the full list of repositories
-        pasteboard_name = "%s.bitbucket.org" % (bbusername.lower())
-        if repo_list is None:
-            rv = hgbb._bb_apicall(uu, "users/%s" % bbusername, None, False)
-            rv = json.loads(rv)
-            repo_list = rv['repositories']
-        create = True
-        for repo in repo_list:
-            if repo['name'] == pasteboard_name:
-                create = False
-        if create:
-            # Now we first create the repository, but we
-            # will only use the creation API, not the bbcreate command.
-            print
-            print "I am now going to create the repository:"
-            print "    ", pasteboard_name
-            print "on BitBucket.org.  This will set up the domain"
-            print "     http://%s" % (pasteboard_name)
-            print "which will point to the current contents of the repo."
-            print
-            loki = raw_input("Press enter to go on, Ctrl-C to exit.")
-            data = dict(name=pasteboard_name)
-            hgbb._bb_apicall(uu, 'repositories', data)
-        # Now we clone
-        pasteboard_path = os.path.join(os.environ["YT_DEST"], "src",
-                                       pasteboard_name)
-        if os.path.isdir(pasteboard_path):
-            print "Found an existing clone of the pasteboard repo:"
-            print "    ", pasteboard_path
-        else:
-            print
-            print "I will now clone a copy of your pasteboard repo."
-            print
-            loki = raw_input("Press enter to go on, Ctrl-C to exit.")
-            commands.clone(uu, "https://%s@bitbucket.org/%s/%s" % (
-                             bbusername, bbusername, pasteboard_name),
-                           pasteboard_path)
-            pbtemplate_path = os.path.join(supp_path, "pasteboard_template")
-            pb_hgrc_path = os.path.join(pasteboard_path, ".hg", "hgrc")
-            cedit.config.setoption(uu, [pb_hgrc_path],
-                                   "paths.pasteboard = " + pbtemplate_path)
-            if create:
-                # We have to pull in the changesets from the pasteboard.
-                pb_repo = hg.repository(uu, pasteboard_path)
-                commands.pull(uu, pb_repo,
-                              os.path.join(supp_path, "pasteboard_template"))
-        if ytcfg.get("yt","pasteboard_repo") != pasteboard_path:
-            print
-            print "Now setting the pasteboard_repo option in"
-            print "~/.yt/config to point to %s" % (pasteboard_path)
-            print
-            loki = raw_input("Press enter to go on, Ctrl-C to exit.")
-            dotyt_path = os.path.expanduser("~/.yt")
-            if not os.path.isdir(dotyt_path):
-                print "There's no directory:"
-                print "    ", dotyt_path
-                print "I will now create it."
-                print
-                loki = raw_input("Press enter to go on, Ctrl-C to exit.")
-                os.mkdir(dotyt_path)
-            ytcfg_path = os.path.expanduser("~/.yt/config")
-            cedit.config.setoption(uu, [ytcfg_path],
-                        "yt.pasteboard_repo=%s" % (pasteboard_path))
-        try:
-            import pygments
-            install_pygments = False
-        except ImportError:
-            install_pygments = True
-        if install_pygments:
-            print "You are missing the Pygments package.  Installing."
-            import pip
-            rv = pip.main(["install", "pygments"])
-            if rv == 1:
-                print "Unable to install Pygments.  Please report this bug to yt-users."
-                sys.exit(1)
         try:
             import lxml
             install_lxml = False
         print
         print "All done!"
         print
-        print "You're now set up to use the 'yt pasteboard' command"
-        print "as well as develop using Mercurial and BitBucket."
+        print "You're now set up to develop using Mercurial and BitBucket."
         print
         print "Good luck!"
 
-    @cmdln.option("-o", "--open-browser", action="store_true",
-                  default = False, dest='open_browser',
-                  help="Open a web browser.")
-    @cmdln.option("-p", "--port", action="store",
-                  default = 0, dest='port',
-                  help="Port to listen on")
-    @cmdln.option("-f", "--find", action="store_true",
-                  default = False, dest="find",
-                  help="At startup, find all *.hierarchy files in the CWD")
-    @cmdln.option("-d", "--debug", action="store_true",
-                  default = False, dest="debug",
-                  help="Add a debugging mode for cell execution")
-    def do_serve(self, subcmd, opts):
+class YTServeCmd(YTCommand):
+    name = "serve"
+    args = (
+            dict(short="-o", long="--open-browser", action="store_true",
+                 default = False, dest='open_browser',
+                 help="Open a web browser."),
+            dict(short="-p", long="--port", action="store",
+                 default = 0, dest='port',
+                 help="Port to listen on"),
+            dict(short="-f", long="--find", action="store_true",
+                 default = False, dest="find",
+                 help="At startup, find all *.hierarchy files in the CWD"),
+            dict(short="-d", long="--debug", action="store_true",
+                 default = False, dest="debug",
+                 help="Add a debugging mode for cell execution")
+            )
+    description = \
         """
         Run the Web GUI Reason
         """
+
+    def __call__(self, args):
         # We have to do a couple things.
         # First, we check that YT_DEST is set.
         if "YT_DEST" not in os.environ:
             print "*** to point to the installation location!        ***"
             print
             sys.exit(1)
-        if opts.port == 0:
+        if args.port == 0:
             # This means, choose one at random.  We do this by binding to a
             # socket and allowing the OS to choose the port for that socket.
             import socket
             sock = socket.socket()
             sock.bind(('', 0))
-            opts.port = sock.getsockname()[-1]
+            args.port = sock.getsockname()[-1]
             del sock
-        elif opts.port == '-1':
+        elif args.port == '-1':
             port = raw_input("Desired yt port? ")
             try:
-                opts.port = int(port)
+                args.port = int(port)
             except ValueError:
                 print "Please try a number next time."
                 return 1
         from yt.gui.reason.extdirect_repl import ExtDirectREPL
         from yt.gui.reason.bottle_mods import uuid_serve_functions, PayloadHandler
         hr = ExtDirectREPL(base_extjs_path)
-        hr.debug = PayloadHandler.debug = opts.debug
-        if opts.find:
+        hr.debug = PayloadHandler.debug = args.debug
+        if args.find:
             # We just have to find them and store references to them.
             command_line = ["pfs = []"]
             for fn in sorted(glob.glob("*/*.hierarchy")):
                 command_line.append("pfs.append(load('%s'))" % fn[:-10])
             hr.execute("\n".join(command_line))
         bottle.debug()
-        uuid_serve_functions(open_browser=opts.open_browser,
-                    port=int(opts.port), repl=hr)
+        uuid_serve_functions(open_browser=args.open_browser,
+                    port=int(args.port), repl=hr)
 
     
-    def _do_remote(self, subcmd, opts):
-        import getpass, sys, socket, time, webbrowser
-        import yt.utilities.pexpect as pex
-
-        host = raw_input('Hostname: ')
-        user = raw_input('User: ')
-        password = getpass.getpass('Password: ')
-
-        sock = socket.socket()
-        sock.bind(('', 0))
-        port = sock.getsockname()[-1]
-        del sock
-
-        child = pex.spawn('ssh -L %s:localhost:%s -l %s %s'%(port, port, user, host))
-        ssh_newkey = 'Are you sure you want to continue connecting'
-        i = child.expect([pex.TIMEOUT, ssh_newkey, 'password: '])
-        if i == 0: # Timeout
-            print 'ERROR!'
-            print 'SSH could not login. Here is what SSH said:'
-            print child.before, child.after
-            return 1
-        if i == 1: # SSH does not have the public key. Just accept it.
-            child.sendline ('yes')
-            child.expect ('password: ')
-            i = child.expect([pex.TIMEOUT, 'password: '])
-            if i == 0: # Timeout
-                print 'ERROR!'
-                print 'SSH could not login. Here is what SSH said:'
-                print child.before, child.after
-                return 1
-        print "Sending password"
-        child.sendline(password)
-        del password
-        print "Okay, sending serving command"
-        child.sendline('yt serve -p -1')
-        print "Waiting ..."
-        child.expect('Desired yt port?')
-        child.sendline("%s" % port)
-        child.expect('     http://localhost:([0-9]*)/(.+)/\r')
-        print "Got:", child.match.group(1), child.match.group(2)
-        port, urlprefix = child.match.group(1), child.match.group(2)
-        print "Sleeping one second and opening browser"
-        time.sleep(1)
-        webbrowser.open("http://localhost:%s/%s/" % (port, urlprefix))
-        print "Press Ctrl-C to terminate session"
-        child.readlines()
-        while 1:
-            time.sleep(1)
-
-    @cmdln.option("-R", "--repo", action="store", type="string",
-                  dest="repo", default=".", help="Repository to upload")
-    def do_hubsubmit(self, subcmd, opts):
+class YTHubSubmitCmd(YTCommand):
+    name = "hub_submit"
+    args = (
+            dict(long="--repo", action="store", type=str,
+                 dest="repo", default=".", help="Repository to upload"),
+           )
+    description = \
         """
         Submit a mercurial repository to the yt Hub
         (http://hub.yt-project.org/), creating a BitBucket repo in the process
         if necessary.
+        """
 
-        ${cmd_usage}
-        ${cmd_option_list}
-        """
+    def __call__(self, args):
         import imp
         from mercurial import hg, ui, commands, error, config
         uri = "http://hub.yt-project.org/3rdparty/API/api.php"
         hgbb = imp.load_module("hgbb", *result)
         uu = ui.ui()
         try:
-            repo = hg.repository(uu, opts.repo)
+            repo = hg.repository(uu, args.repo)
             conf = config.config()
-            if os.path.exists(os.path.join(opts.repo,".hg","hgrc")):
-                conf.read(os.path.join(opts.repo, ".hg", "hgrc"))
+            if os.path.exists(os.path.join(args.repo,".hg","hgrc")):
+                conf.read(os.path.join(args.repo, ".hg", "hgrc"))
             needs_bb = True
             if "paths" in conf.sections():
                 default = conf['paths'].get("default", "")
                             break
         except error.RepoError:
             print "Unable to find repo at:"
-            print "   %s" % (os.path.abspath(opts.repo))
+            print "   %s" % (os.path.abspath(args.repo))
             print
             print "Would you like to initialize one?  If this message"
             print "surprises you, you should perhaps press Ctrl-C to quit."
                 print "Okay, rad -- we'll let you handle it and get back to",
                 print " us."
                 return 1
-            commands.init(uu, dest=opts.repo)
-            repo = hg.repository(uu, opts.repo)
+            commands.init(uu, dest=args.repo)
+            repo = hg.repository(uu, args.repo)
             commands.add(uu, repo)
             commands.commit(uu, repo, message="Initial automated import by yt")
             needs_bb = True
                 print
                 print "to get set up and ready to go."
                 return 1
-            bb_repo_name = os.path.basename(os.path.abspath(opts.repo))
+            bb_repo_name = os.path.basename(os.path.abspath(args.repo))
             print
             print "I am now going to create the repository:"
             print "    ", bb_repo_name
         rv = urllib2.urlopen(req).read()
         print rv
 
-    def do_upload_image(self, subcmd, opts, filename):
+class YTUploadImageCmd(YTCommand):
+    args = (dict(short="file", type=str))
+    description = \
         """
         Upload an image to imgur.com.  Must be PNG.
 
-        ${cmd_usage} 
-        ${cmd_option_list}
         """
+
+    def __call__(self, args):
+        filename = args.file
         if not filename.endswith(".png"):
             print "File must be a PNG file!"
             return 1
             print
             pprint.pprint(rv)
 
-    @add_cmd_options(["width", "unit", "center","enhance",'outputfn',
-                      "field", "cmap", "contours", "viewpoint",
-                      "pixels","up","valrange","log","contour_width"])
-    @check_args
-    def do_render(self, subcmd, opts, arg):
+class YTRenderCmd(YTCommand):
+        
+    args = ("width", "unit", "center","enhance",'outputfn',
+            "field", "cmap", "contours", "viewpoint",
+            "pixels","up","valrange","log","contour_width", "pf")
+    name = "render"
+    description = \
         """
         Create a simple volume rendering
+        """
 
-        ${cmd_usage}
-        ${cmd_option_list}
-        """
-        pf = _fix_pf(arg)
-        center = opts.center
-        if opts.center == (-1,-1,-1):
+    def __call__(self, args):
+        pf = args.pf
+        center = args.center
+        if args.center == (-1,-1,-1):
             mylog.info("No center fed in; seeking.")
             v, center = pf.h.find_max("Density")
-        elif opts.center is None:
+        elif args.center is None:
             center = 0.5*(pf.domain_left_edge + pf.domain_right_edge)
         center = na.array(center)
 
-        L = opts.viewpoint
+        L = args.viewpoint
         if L is None:
             L = [1.]*3
-        L = na.array(opts.viewpoint)
+        L = na.array(args.viewpoint)
 
-        unit = opts.unit
+        unit = args.unit
         if unit is None:
             unit = '1'
-        width = opts.width
+        width = args.width
         if width is None:
             width = 0.5*(pf.domain_right_edge - pf.domain_left_edge)
         width /= pf[unit]
 
-        N = opts.pixels
+        N = args.pixels
         if N is None:
             N = 512 
         
-        up = opts.up
+        up = args.up
         if up is None:
             up = [0.,0.,1.]
             
-        field = opts.field
+        field = args.field
         if field is None:
             field = 'Density'
         
-        log = opts.takelog
+        log = args.takelog
         if log is None:
             log = True
 
-        myrange = opts.valrange
+        myrange = args.valrange
         if myrange is None:
             roi = pf.h.region(center, center-width, center+width)
             mi, ma = roi.quantities['Extrema'](field)[0]
         else:
             mi, ma = myrange[0], myrange[1]
 
-        n_contours = opts.contours
+        n_contours = args.contours
         if n_contours is None:
             n_contours = 7
 
-        contour_width = opts.contour_width
+        contour_width = args.contour_width
 
-        cmap = opts.cmap
+        cmap = args.cmap
         if cmap is None:
             cmap = 'jet'
         tf = ColorTransferFunction((mi-2, ma+2))
         cam = pf.h.camera(center, L, width, (N,N), transfer_function=tf)
         image = cam.snapshot()
 
-        if opts.enhance:
+        if args.enhance:
             for i in range(3):
                 image[:,:,i] = image[:,:,i]/(image[:,:,i].mean() + 5.*image[:,:,i].std())
             image[image>1.0]=1.0
             
-        save_name = opts.output
+        save_name = args.output
         if save_name is None:
             save_name = "%s"%pf+"_"+field+"_rendering.png"
         if not '.png' in save_name:
         
 
 def run_main():
-    for co in ["--parallel", "--paste"]:
-        if co in sys.argv: del sys.argv[sys.argv.index(co)]
-    YT = YTCommands()
-    sys.exit(YT.main())
+    args = parser.parse_args()
+    args.func(args)
 
 if __name__ == "__main__": run_main()

yt/utilities/pasteboard.py

-"""
-Author: Matthew Turk <matthewturk@gmail.com>
-Affiliation: Columbia University
-Homepage: http://yt-project.org/
-License:
-  Copyright (C) 2011 Matthew Turk.  All Rights Reserved.
-
-  This file is part of yt.
-
-  yt is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-from mercurial import ui, repo, commands, hg
-import json
-import os
-import time
-import uuid
-import urllib
-
-from yt.config import ytcfg
-
-def _get_last_mod(filectx):
-    rev = filectx.filectx(filectx.filerev())
-    return rev
-
-class PostInventory(object):
-    def __init__(self, uu = None, repo_fn = None):
-        if uu is None: uu = ui.ui()
-        if repo_fn is None: repo_fn = ytcfg.get("yt","pasteboard_repo")
-        if repo_fn == '':
-            raise KeyError("~/.yt/config:[yt]pasteboard_repo")
-        self.repo_fn = repo_fn
-        self.bbrepo = hg.repository(uu, repo_fn)
-        config_fn = os.path.join(repo_fn, ".hg", "hgrc")
-        uu.readconfig(config_fn)
-        commands.pull(uu, self.bbrepo)
-        commands.update(uu, self.bbrepo, clean=True)
-        if not os.path.exists(os.path.join(repo_fn, "posts")):
-            os.makedirs(os.path.join(repo_fn, "posts"))
-        if not os.path.exists(os.path.join(repo_fn, "html")):
-            os.makedirs(os.path.join(repo_fn, "html"))
-        self.uu = uu
-
-    def regenerate_posts(self):
-        self.posts = []
-        for file in self.bbrepo["tip"]:
-            if file.startswith("posts/") and file.count("/") == 1 \
-               and not file.endswith(".desc"):
-                filectx = self.bbrepo["tip"][file]
-                last_mod = _get_last_mod(filectx).date()
-                self.posts.append((last_mod[0] + last_mod[1], file))
-        self.posts.sort()
-        self.posts = self.posts[::-1]
-
-    def add_post(self, filename, desc = None,
-                 uu = None, highlight = True, push = True):
-        # We assume the post filename exists in the current space
-        self.regenerate_posts()
-        if uu is None: uu = self.uu
-        prefix = uuid.uuid4()
-        name = "%s-%s" % (prefix, os.path.basename(filename))
-        name_noext = name.replace(".","-")
-        hfn = "html/%s.html" % (name_noext)
-        pfn = "posts/%s" % (name)
-        abs_pfn = os.path.join(self.repo_fn, pfn)
-        abs_hfn = os.path.join(self.repo_fn, hfn)
-        if desc is not None:
-            open(abs_pfn + ".desc", "w").write(desc)
-        self.posts.insert(0, (int(time.time()), "posts/%s" % name))
-        if not os.path.exists(abs_pfn):
-            open(abs_pfn,"w").write(open(filename).read())
-        inv_fname = self.update_inventory()
-        if highlight and not name.endswith(".html"):
-            from pygments.cmdline import main as pygmain
-            rv = pygmain(["pygmentize", "-o", abs_hfn,
-                          "-O", "full", abs_pfn])
-        if not highlight or rv:
-            content = open(abs_pfn).read()
-            open(abs_hfn, "w").write(
-                "<HTML><BODY><PRE>" + content + "</PRE></BODY></HTML>")
-        to_manage = [abs_pfn, abs_hfn]
-        if desc is not None: to_manage.append(abs_pfn + ".desc")
-        commands.add(uu, self.bbrepo, *to_manage)
-        commands.commit(uu, self.bbrepo, *(to_manage + [inv_fname]),
-                        message="Adding %s" % name)
-        if push: commands.push(uu, self.bbrepo)
-
-    def update_inventory(self):
-        tip = self.bbrepo["tip"]
-        vals = []
-        for t, pfn in self.posts:
-            dfn = pfn + ".desc"
-            if dfn in tip:
-                d = tip[dfn].data()
-                last_mod =_get_last_mod(tip[dfn])
-                last_hash = last_mod.hex()
-                uname = last_mod.user()
-            elif pfn not in tip:
-                abs_pfn = os.path.join(self.repo_fn, pfn)
-                uname = self.uu.config("ui","username")
-                if os.path.exists(abs_pfn + ".desc"):
-                    d = open(abs_pfn + ".desc").read()
-                else:
-                    d = open(abs_pfn).read()
-                last_hash = "tip"
-            else:
-                d = tip[pfn].data()
-                last_mod = _get_last_mod(tip[pfn])
-                last_hash = last_mod.hex()
-                uname = last_mod.user()
-            if len(d) > 80: d = d[:77] + "..."
-            name_noext = pfn[6:].replace(".","-")
-            vals.append(dict(modified = time.ctime(t),
-                             modtime = t,
-                             lastmod_hash = last_hash,
-                             fullname = pfn,
-                             htmlname = "html/%s.html" % name_noext,
-                             name = pfn[43:], # 6 for posts/ then 36 for UUID
-                             username = uname,
-                             descr = d)) 
-        fn = os.path.join(self.repo_fn, "inventory.json")
-        f = open(fn, "w")
-        f.write("var inventory_data = ")
-        json.dump(vals, f, indent = 1)
-        f.write(";")
-        return fn
-
-def retrieve_pastefile(username, paste_id, output_fn = None):
-    # First we get the username's inventory.json
-    s = urllib.urlopen("http://%s.bitbucket.org/inventory.json" % (username))
-    data = s.read()
-    # This is an ugly, ugly hack for my lack of understanding of how best to
-    # handle this JSON stuff.
-    data = data[data.find("=")+1:data.rfind(";")] 
-    #import pdb;pdb.set_trace()
-    inv = json.loads(data)
-    k = None
-    if len(paste_id) == 36:
-        # Then this is a UUID
-        for k in inv:
-            if k['fullname'][6:42] == paste_id: break
-    elif len(paste_id) == 10:
-        pp = int(paste_id)
-        for k in inv:
-            if k['modtime'] == pp: break
-    if k is None: raise KeyError(k)
-    # k is our key
-    url = "http://%s.bitbucket.org/%s" % (username, k['fullname'])
-    s = urllib.urlopen(url)
-    data = s.read()
-    if output_fn is not None:
-        if os.path.exists(output_fn): raise IOError(output_fn)
-        open(output_fn, "w").write(data)
-    else:
-        print data

yt/utilities/pexpect.py

-"""Pexpect is a Python module for spawning child applications and controlling
-them automatically. Pexpect can be used for automating interactive applications
-such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
-scripts for duplicating software package installations on different servers. It
-can be used for automated software testing. Pexpect is in the spirit of Don
-Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
-require TCL and Expect or require C extensions to be compiled. Pexpect does not
-use C, Expect, or TCL extensions. It should work on any platform that supports
-the standard Python pty module. The Pexpect interface focuses on ease of use so
-that simple tasks are easy.
-
-There are two main interfaces to Pexpect -- the function, run() and the class,
-spawn. You can call the run() function to execute a command and return the
-output. This is a handy replacement for os.system().
-
-For example::
-
-    pexpect.run('ls -la')
-
-The more powerful interface is the spawn class. You can use this to spawn an
-external child command and then interact with the child by sending lines and
-expecting responses.
-
-For example::
-
-    child = pexpect.spawn('scp foo myname@host.example.com:.')
-    child.expect ('Password:')
-    child.sendline (mypassword)
-
-This works even for commands that ask for passwords or other input outside of
-the normal stdio streams.
-
-Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
-Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
-vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
-Geoffrey Marshall, Francisco Lourenco, Glen Mabey, Karthik Gurusamy, Fernando
-Perez, Corey Minyard, Jon Cohen, Guillaume Chazarain, Andrew Ryan, Nick
-Craig-Wood, Andrew Stone, Jorgen Grahn (Let me know if I forgot anyone.)
-
-Free, open source, and all that good stuff.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Pexpect Copyright (c) 2008 Noah Spurrier
-http://pexpect.sourceforge.net/
-
-$Id: pexpect.py 507 2007-12-27 02:40:52Z noah $
-"""
-
-try:
-    import os, sys, time
-    import select
-    import string
-    import re
-    import struct
-    import resource
-    import types
-    import pty
-    import tty
-    import termios
-    import fcntl
-    import errno
-    import traceback
-    import signal
-except ImportError, e:
-    raise ImportError (str(e) + """
-
-A critical module was not found. Probably this operating system does not
-support it. Pexpect is intended for UNIX-like operating systems.""")
-
-__version__ = '2.3'
-__revision__ = '$Revision: 399 $'
-__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'run', 'which',
-    'split_command_line', '__version__', '__revision__']
-
-# Exception classes used by this module.
-class ExceptionPexpect(Exception):
-
-    """Base class for all exceptions raised by this module.
-    """
-
-    def __init__(self, value):
-
-        self.value = value
-
-    def __str__(self):
-
-        return str(self.value)
-
-    def get_trace(self):
-
-        """This returns an abbreviated stack trace with lines that only concern
-        the caller. In other words, the stack trace inside the Pexpect module
-        is not included. """
-
-        tblist = traceback.extract_tb(sys.exc_info()[2])
-        #tblist = filter(self.__filter_not_pexpect, tblist)
-        tblist = [item for item in tblist if self.__filter_not_pexpect(item)]
-        tblist = traceback.format_list(tblist)
-        return ''.join(tblist)
-
-    def __filter_not_pexpect(self, trace_list_item):
-
-        """This returns True if list item 0 the string 'pexpect.py' in it. """
-
-        if trace_list_item[0].find('pexpect.py') == -1:
-            return True
-        else:
-            return False
-
-class EOF(ExceptionPexpect):
-
-    """Raised when EOF is read from a child. This usually means the child has exited."""
-
-class TIMEOUT(ExceptionPexpect):
-
-    """Raised when a read time exceeds the timeout. """
-
-##class TIMEOUT_PATTERN(TIMEOUT):
-##    """Raised when the pattern match time exceeds the timeout.
-##    This is different than a read TIMEOUT because the child process may
-##    give output, thus never give a TIMEOUT, but the output
-##    may never match a pattern.
-##    """
-##class MAXBUFFER(ExceptionPexpect):
-##    """Raised when a scan buffer fills before matching an expected pattern."""
-
-def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None, logfile=None, cwd=None, env=None):
-
-    """
-    This function runs the given command; waits for it to finish; then
-    returns all output as a string. STDERR is included in output. If the full
-    path to the command is not given then the path is searched.
-
-    Note that lines are terminated by CR/LF (\\r\\n) combination even on
-    UNIX-like systems because this is the standard for pseudo ttys. If you set
-    'withexitstatus' to true, then run will return a tuple of (command_output,
-    exitstatus). If 'withexitstatus' is false then this returns just
-    command_output.
-
-    The run() function can often be used instead of creating a spawn instance.
-    For example, the following code uses spawn::
-
-        from pexpect import *
-        child = spawn('scp foo myname@host.example.com:.')
-        child.expect ('(?i)password')
-        child.sendline (mypassword)
-
-    The previous code can be replace with the following::
-
-        from pexpect import *
-        run ('scp foo myname@host.example.com:.', events={'(?i)password': mypassword})
-
-    Examples
-    ========
-
-    Start the apache daemon on the local machine::
-
-        from pexpect import *
-        run ("/usr/local/apache/bin/apachectl start")
-
-    Check in a file using SVN::
-
-        from pexpect import *
-        run ("svn ci -m 'automatic commit' my_file.py")
-
-    Run a command and capture exit status::
-
-        from pexpect import *
-        (command_output, exitstatus) = run ('ls -l /bin', withexitstatus=1)
-
-    Tricky Examples
-    ===============
-
-    The following will run SSH and execute 'ls -l' on the remote machine. The
-    password 'secret' will be sent if the '(?i)password' pattern is ever seen::
-
-        run ("ssh username@machine.example.com 'ls -l'", events={'(?i)password':'secret\\n'})
-
-    This will start mencoder to rip a video from DVD. This will also display
-    progress ticks every 5 seconds as it runs. For example::
-
-        from pexpect import *
-        def print_ticks(d):
-            print d['event_count'],
-        run ("mencoder dvd://1 -o video.avi -oac copy -ovc copy", events={TIMEOUT:print_ticks}, timeout=5)
-
-    The 'events' argument should be a dictionary of patterns and responses.
-    Whenever one of the patterns is seen in the command out run() will send the
-    associated response string. Note that you should put newlines in your
-    string if Enter is necessary. The responses may also contain callback
-    functions. Any callback is function that takes a dictionary as an argument.
-    The dictionary contains all the locals from the run() function, so you can
-    access the child spawn object or any other variable defined in run()
-    (event_count, child, and extra_args are the most useful). A callback may
-    return True to stop the current run process otherwise run() continues until
-    the next event. A callback may also return a string which will be sent to
-    the child. 'extra_args' is not used by directly run(). It provides a way to
-    pass data to a callback function through run() through the locals
-    dictionary passed to a callback. """
-
-    if timeout == -1:
-        child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env)
-    else:
-        child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile, cwd=cwd, env=env)
-    if events is not None:
-        patterns = events.keys()
-        responses = events.values()
-    else:
-        patterns=None # We assume that EOF or TIMEOUT will save us.
-        responses=None
-    child_result_list = []
-    event_count = 0
-    while 1:
-        try:
-            index = child.expect (patterns)
-            if type(child.after) in types.StringTypes:
-                child_result_list.append(child.before + child.after)
-            else: # child.after may have been a TIMEOUT or EOF, so don't cat those.
-                child_result_list.append(child.before)
-            if type(responses[index]) in types.StringTypes:
-                child.send(responses[index])
-            elif type(responses[index]) is types.FunctionType:
-                callback_result = responses[index](locals())
-                sys.stdout.flush()
-                if type(callback_result) in types.StringTypes:
-                    child.send(callback_result)
-                elif callback_result:
-                    break
-            else:
-                raise TypeError ('The callback must be a string or function type.')
-            event_count = event_count + 1
-        except TIMEOUT, e:
-            child_result_list.append(child.before)
-            break
-        except EOF, e:
-            child_result_list.append(child.before)
-            break
-    child_result = ''.join(child_result_list)
-    if withexitstatus:
-        child.close()
-        return (child_result, child.exitstatus)
-    else:
-        return child_result
-
-class spawn (object):
-
-    """This is the main class interface for Pexpect. Use this class to start
-    and control child applications. """
-
-    def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None):
-
-        """This is the constructor. The command parameter may be a string that
-        includes a command and any arguments to the command. For example::
-
-            child = pexpect.spawn ('/usr/bin/ftp')
-            child = pexpect.spawn ('/usr/bin/ssh user@example.com')
-            child = pexpect.spawn ('ls -latr /tmp')
-
-        You may also construct it with a list of arguments like so::
-
-            child = pexpect.spawn ('/usr/bin/ftp', [])
-            child = pexpect.spawn ('/usr/bin/ssh', ['user@example.com'])
-            child = pexpect.spawn ('ls', ['-latr', '/tmp'])
-
-        After this the child application will be created and will be ready to
-        talk to. For normal use, see expect() and send() and sendline().
-
-        Remember that Pexpect does NOT interpret shell meta characters such as
-        redirect, pipe, or wild cards (>, |, or *). This is a common mistake.
-        If you want to run a command and pipe it through another command then
-        you must also start a shell. For example::
-
-            child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"')
-            child.expect(pexpect.EOF)
-
-        The second form of spawn (where you pass a list of arguments) is useful
-        in situations where you wish to spawn a command and pass it its own
-        argument list. This can make syntax more clear. For example, the
-        following is equivalent to the previous example::
-
-            shell_cmd = 'ls -l | grep LOG > log_list.txt'
-            child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
-            child.expect(pexpect.EOF)
-
-        The maxread attribute sets the read buffer size. This is maximum number
-        of bytes that Pexpect will try to read from a TTY at one time. Setting
-        the maxread size to 1 will turn off buffering. Setting the maxread
-        value higher may help performance in cases where large amounts of
-        output are read back from the child. This feature is useful in
-        conjunction with searchwindowsize.
-
-        The searchwindowsize attribute sets the how far back in the incomming
-        seach buffer Pexpect will search for pattern matches. Every time
-        Pexpect reads some data from the child it will append the data to the
-        incomming buffer. The default is to search from the beginning of the
-        imcomming buffer each time new data is read from the child. But this is
-        very inefficient if you are running a command that generates a large
-        amount of data where you want to match The searchwindowsize does not
-        effect the size of the incomming data buffer. You will still have
-        access to the full buffer after expect() returns.
-
-        The logfile member turns on or off logging. All input and output will
-        be copied to the given file object. Set logfile to None to stop
-        logging. This is the default. Set logfile to sys.stdout to echo
-        everything to standard output. The logfile is flushed after each write.
-
-        Example log input and output to a file::
-
-            child = pexpect.spawn('some_command')
-            fout = file('mylog.txt','w')
-            child.logfile = fout
-
-        Example log to stdout::
-
-            child = pexpect.spawn('some_command')
-            child.logfile = sys.stdout
-
-        The logfile_read and logfile_send members can be used to separately log
-        the input from the child and output sent to the child. Sometimes you
-        don't want to see everything you write to the child. You only want to
-        log what the child sends back. For example::
-        
-            child = pexpect.spawn('some_command')
-            child.logfile_read = sys.stdout
-
-        To separately log output sent to the child use logfile_send::
-        
-            self.logfile_send = fout
-
-        The delaybeforesend helps overcome a weird behavior that many users
-        were experiencing. The typical problem was that a user would expect() a
-        "Password:" prompt and then immediately call sendline() to send the
-        password. The user would then see that their password was echoed back
-        to them. Passwords don't normally echo. The problem is caused by the
-        fact that most applications print out the "Password" prompt and then
-        turn off stdin echo, but if you send your password before the
-        application turned off echo, then you get your password echoed.
-        Normally this wouldn't be a problem when interacting with a human at a
-        real keyboard. If you introduce a slight delay just before writing then
-        this seems to clear up the problem. This was such a common problem for
-        many users that I decided that the default pexpect behavior should be
-        to sleep just before writing to the child application. 1/20th of a
-        second (50 ms) seems to be enough to clear up the problem. You can set
-        delaybeforesend to 0 to return to the old behavior. Most Linux machines
-        don't like this to be below 0.03. I don't know why.
-
-        Note that spawn is clever about finding commands on your path.
-        It uses the same logic that "which" uses to find executables.
-
-        If you wish to get the exit status of the child you must call the
-        close() method. The exit or signal status of the child will be stored
-        in self.exitstatus or self.signalstatus. If the child exited normally
-        then exitstatus will store the exit return code and signalstatus will
-        be None. If the child was terminated abnormally with a signal then
-        signalstatus will store the signal value and exitstatus will be None.
-        If you need more detail you can also read the self.status member which
-        stores the status returned by os.waitpid. You can interpret this using
-        os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. """
-
-        self.STDIN_FILENO = pty.STDIN_FILENO
-        self.STDOUT_FILENO = pty.STDOUT_FILENO
-        self.STDERR_FILENO = pty.STDERR_FILENO
-        self.stdin = sys.stdin
-        self.stdout = sys.stdout
-        self.stderr = sys.stderr
-
-        self.searcher = None
-        self.ignorecase = False
-        self.before = None
-        self.after = None
-        self.match = None
-        self.match_index = None
-        self.terminated = True
-        self.exitstatus = None
-        self.signalstatus = None
-        self.status = None # status returned by os.waitpid
-        self.flag_eof = False
-        self.pid = None
-        self.child_fd = -1 # initially closed
-        self.timeout = timeout
-        self.delimiter = EOF
-        self.logfile = logfile
-        self.logfile_read = None # input from child (read_nonblocking)
-        self.logfile_send = None # output to send (send, sendline)
-        self.maxread = maxread # max bytes to read at one time into buffer
-        self.buffer = '' # This is the read buffer. See maxread.
-        self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched.
-        # Most Linux machines don't like delaybeforesend to be below 0.03 (30 ms).
-        self.delaybeforesend = 0.05 # Sets sleep time used just before sending data to child. Time in seconds.
-        self.delayafterclose = 0.1 # Sets delay in close() method to allow kernel time to update process status. Time in seconds.
-        self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds.
-        self.softspace = False # File-like object.
-        self.name = '<' + repr(self) + '>' # File-like object.
-        self.encoding = None # File-like object.
-        self.closed = True # File-like object.
-        self.cwd = cwd
-        self.env = env
-        self.__irix_hack = (sys.platform.lower().find('irix')>=0) # This flags if we are running on irix
-        # Solaris uses internal __fork_pty(). All others use pty.fork().
-        if (sys.platform.lower().find('solaris')>=0) or (sys.platform.lower().find('sunos5')>=0):
-            self.use_native_pty_fork = False
-        else:
-            self.use_native_pty_fork = True
-
-
-        # allow dummy instances for subclasses that may not use command or args.
-        if command is None:
-            self.command = None
-            self.args = None
-            self.name = '<pexpect factory incomplete>'
-        else:
-            self._spawn (command, args)
-
-    def __del__(self):
-
-        """This makes sure that no system resources are left open. Python only
-        garbage collects Python objects. OS file descriptors are not Python
-        objects, so they must be handled explicitly. If the child file
-        descriptor was opened outside of this class (passed to the constructor)
-        then this does not close it. """
-
-        if not self.closed:
-            # It is possible for __del__ methods to execute during the
-            # teardown of the Python VM itself. Thus self.close() may
-            # trigger an exception because os.close may be None.
-            # -- Fernando Perez
-            try:
-                self.close()
-            except AttributeError:
-                pass
-
-    def __str__(self):
-
-        """This returns a human-readable string that represents the state of
-        the object. """
-
-        s = []
-        s.append(repr(self))
-        s.append('version: ' + __version__ + ' (' + __revision__ + ')')
-        s.append('command: ' + str(self.command))
-        s.append('args: ' + str(self.args))
-        s.append('searcher: ' + str(self.searcher))
-        s.append('buffer (last 100 chars): ' + str(self.buffer)[-100:])
-        s.append('before (last 100 chars): ' + str(self.before)[-100:])
-        s.append('after: ' + str(self.after))
-        s.append('match: ' + str(self.match))
-        s.append('match_index: ' + str(self.match_index))
-        s.append('exitstatus: ' + str(self.exitstatus))
-        s.append('flag_eof: ' + str(self.flag_eof))
-        s.append('pid: ' + str(self.pid))
-        s.append('child_fd: ' + str(self.child_fd))
-        s.append('closed: ' + str(self.closed))
-        s.append('timeout: ' + str(self.timeout))
-        s.append('delimiter: ' + str(self.delimiter))
-        s.append('logfile: ' + str(self.logfile))
-        s.append('logfile_read: ' + str(self.logfile_read))
-        s.append('logfile_send: ' + str(self.logfile_send))
-        s.append('maxread: ' + str(self.maxread))
-        s.append('ignorecase: ' + str(self.ignorecase))
-        s.append('searchwindowsize: ' + str(self.searchwindowsize))
-        s.append('delaybeforesend: ' + str(self.delaybeforesend))
-        s.append('delayafterclose: ' + str(self.delayafterclose))
-        s.append('delayafterterminate: ' + str(self.delayafterterminate))
-        return '\n'.join(s)
-
-    def _spawn(self,command,args=[]):
-
-        """This starts the given command in a child process. This does all the
-        fork/exec type of stuff for a pty. This is called by __init__. If args
-        is empty then command will be parsed (split on spaces) and args will be
-        set to parsed arguments. """
-
-        # The pid and child_fd of this object get set by this method.
-        # Note that it is difficult for this method to fail.
-        # You cannot detect if the child process cannot start.
-        # So the only way you can tell if the child process started
-        # or not is to try to read from the file descriptor. If you get
-        # EOF immediately then it means that the child is already dead.
-        # That may not necessarily be bad because you may haved spawned a child
-        # that performs some task; creates no stdout output; and then dies.
-
-        # If command is an int type then it may represent a file descriptor.
-        if type(command) == type(0):
-            raise ExceptionPexpect ('Command is an int type. If this is a file descriptor then maybe you want to use fdpexpect.fdspawn which takes an existing file descriptor instead of a command string.')
-
-        if type (args) != type([]):