szaydel
11/12/2012 - 4:48 PM

Using pyCLI to create some commands and subcommands.

Using pyCLI to create some commands and subcommands.

#!/usr/bin/python

import unittest
import argparse 
from pprint import pprint

class F(object):
  def __init__(self, name):
    self.name = name
  def main(self, app, params):
    pprint([ self.name, self, params ])
    print "Hello, I'm %s." % self.name
    
def get_simple_parser( ):
  parser = argparse.ArgumentParser()
  # flesh it out a bit with a no-op option
  parser.add_argument('-d', '--debug', action='store_true')
  return parser

class TestSubparserDefaultFun(unittest.TestCase):
  def setUp(self):
    self.parser = get_simple_parser( )
    setup_a(self.parser)

  def parse_missing_subcommand_args(self):
    pprint(parser.parse_args(prep('')))

  def donttest_required_subcommand_behavior(self):
    self.parser.parse_args( )

  def test_optional_subcommand_behavior(self):
    self.parser.parse_args(prep('  '))


def setup_a(parser, name='lalala'):
  desc = """This is a long description on a simple command."""
  # goal, make qux the default
  # default = 'qux'
  kwds = dict( title='Title Group A',
               dest='command',
               description = desc,
               prog= "my program",
               # XXX: PATCH
               default = 'qux',
               help='some help on group A')
  subparsers = parser.add_subparsers(**kwds)
  for x in [ 'qux', 'fux', 'bux', 'lux' ]:
    f = F(x)
    kwds = dict( description = "long desc of %s" % x,
               )
               #  default= 'qux')
    p = subparsers.add_parser(x, **kwds)
    p.set_defaults(run=f.main)

def prep(args):
  return args.split( )

def main( ):
  parser = get_simple_parser( )
  #sub = parser.add_subparsers()
  #sub.add_parser("info")
  #parser.add_argument("paths", "+")
  #pprint(parser.parse_args(["foo", "bar"]))

  # add some subcommands
  setup_a(parser)

  #
  pprint(parser.parse_args(prep('')))
  pprint(parser.parse_args(prep('')))
  

if __name__ == '__main__':
  unittest.main( )

#####
# EOF

#!/usr/bin/python

"""
Simple app using argparse.

How can I provide a bunch of subcommands, but make one of them a default?

"""


from pprint import pprint
import argparse
import logging
log = logging.getLogger(__name__)

class F(object):
  def __init__(self, name):
    self.name = name
  def main(self, app, params):
    pprint([ self.name, self, params ])
    print "Hello, I'm %s." % self.name
    

class Simple(object):
  """

  This is a very simple description.
  We'll simulate it very long here.
  Very long indeed.
  """
  def __init__(self):
    desc = type(self).__doc__
    self.parser = argparse.ArgumentParser(description=desc)
    self.parser.add_argument('-d', '--debug', action='store_true')
    # dest, title, help, description
    desc = """This is a long description on a simple command."""

    self.setup_a(self.parser)

  def setup_a(self, parser, name='lalala'):
    desc = """This is a long description on a simple command."""
    subparsers = parser.add_subparsers(title='Title Group A',
                                       dest='command',
                                       default='qux',
                                       description = desc,
                                       help='some help on group A')
    for x in [ 'qux', 'fux', 'bux', 'lux' ]:
      f = F(x)
      kwds = dict( description = "long desc of %s" % x,
                 )
                 #  default= 'qux')
      p = subparsers.add_parser(x, **kwds)
      p.set_defaults(run=f.main)


  def parse(self, argv):
    return self.parser.parse_args(argv)

  def run(self, args=None):
    if args is None:
      import sys
      args = self.parse(sys.argv[1:])
    if hasattr(args, 'run'):
      args.run(self, args)
    else:
      self.main(args)
      
  def main(self, app, params):
    log.warn("hello world warn")
    log.debug("hello world debug")
    log.info("hello world info")
    log.error("hello world error")
    log.critical("hello world critical")
    log.fatal("hello world fatal")

    pprint(params)
    print "default"

if __name__ == '__main__':
  app = Simple()
  app.run( )

#####
# EOF

import sys
import commando
from pprint import pprint

__version__ = '0.0.1-dev'

class ParamGroup(commando.param):
  __params__ = ( ('-d', '--debug'), dict(action='store_true' ) )
  def __init__(self):
    params      = self.params( )
    args, kwds  = params[0], params[1]
    self.values = commando.values._make( (args, kwds) )

  def params(self):
    return self.__params__

base_val = commando.values
class TaggedMemo(object):
  subcommand = base_val._make(((), dict()))
  commando   = True
  params     = [ ]
  def __init__(self, name=None):
    default = base_val._make(((name, ), dict( )))
    self.subcommand = getattr(self.main, 'subcommand', default)
    self.params     = [ ]

  def __call__(self, app, params):
    self.main(params)

  def main(self, params):
    print "I'm an unsubclassed Command"
    pprint([self, params])

class DemoRecurse(TaggedMemo):
  @commando.subcommand('far', help='demo far recurse')
  def main(self, params):
    print "used decorator on a subclass"
    
class FooBar(object):
  @commando.subcommand('one', help="one")
  def one(self, app, params):
    print "one"

  @commando.subcommand('two', help="two")
  def two(self, app, params):
    print "two"

  #@commando.command(description="my command description")
  @commando.subcommand('far', help='demo far recurse')
  def main(self, app, params):
    print "used decorator on a subclass"

class Root(object):

  @commando.command(description="my command description")
  @commando.param('-v', '--version', action='version',
                  version='%(prog)s ' + __version__)
  @commando.param('-foo', dest='foo', action='store', type=str)
  @commando.subcommand('init', help="main command")
  @ParamGroup( )
  def main(self, app, params):
    pprint([self, params])

  @commando.subcommand('foo', help="foo command")
  def foo(self, app, params):
    pprint([self, params])
  foo.branch = True

  foo.baz = FooBar( )
  foo.branches = [ 'baz' ]

  #bar = FooBar( )
  #bar.branch = True
  #branch = True
  #branches = [ 'bar' ]

  #bar.branch = True
  #bar.branches = ['qux', 'faz']
  #bar.qux = TaggedMemo('qux')
  #bar.qux.commando = True
  #bar.faz = DemoRecurse( )
  #bar.faz.commando = True

class Application(Root, commando.WeirdApp):
  __subcommands__ = [ FooBar( ), DemoRecurse('demo') ]
  def __init__(self):
    super(Application, self).__init__()
  pass



def main( ):
  #app = Application( )
  #app.run( )
  
  tree = commando.TreeApp(root=Root( ))
  tree.run( )
if __name__ == '__main__':
  main( )

#####
# EOF
#!/usr/bin/python

from cli.log import LoggingApp
from pprint import pprint

"""
Very rough.
"""

class Subcommand(object):
  name = ''
  def __init__(self, handler):
    self.session = handler 

  def options(self):
    return [ ]
  def setup(self, parser):
    self.parser = parser
    for args, kwds in self.options( ):
      parser.add_argument(*args, **kwds)
  def help(self):
    return self.__doc__

  def main(self, app):
    pprint([self, app])
    print self.name

class QuxApp(Subcommand):
  """Qux Does several special things"""
  name = "qux"
class FuxApp(Subcommand):
  """Fux is accidently different."""
  name = "fux"
class BuxApp(Subcommand):
  """Bux seems special, but it's a trick."""
  name = "bux"
class BaxApp(Subcommand):
  """Bax seems special, bat it's a trick."""
  name = "bax"
class FaxApp(Subcommand):
  """Fax is accidently different."""
  name = "fax"
class QaxApp(Subcommand):
  """Qax Does several special things"""
  name = "qax"

class Command(object):
  "Fake help"
  subcommands = { }
  def __init__(self, name, subcommands=None):
    self.subcommands = { }
    self.name  = name
    if subcommands is not None:
      for Flow in subcommands:
        self.addFlow(Flow)

  def __repr__(self):
    return "%s:%s" % (self.name, type(self))
  def subcommand_factory(self, Flow):
    return Flow(self)

  def addFlow(self, Flow):
    flow = self.subcommand_factory(Flow)
    self.subcommands[flow.name] = flow

  def base(self, params):
    pprint(self, params)
    print "Without a subcommand!!"

  def setup(self, parser):
    n = self.name
    self.parser   = parser
    pprint(['before', parser._positionals])
    self.commands = parser.add_subparsers(dest='subcommand',
                                          title="my commands title",
                                          help=self.help( ),
                                          prog="command")
    pprint(['after', parser._positionals])
    parser.set_defaults(run=self.base)
    #p = self.commands.add_parser(None, help='basic help')
    for flow in self.subcommands.values( ):
      #flow = Flow( )
      p = self.commands.add_parser(flow.name, help=flow.help())
      flow.setup(p)
 
  def help(self):
    return self.__doc__

  def main(self, app):
    subcommand = self.subcommands[app.params.subcommand]
    subcommand.main(self)
    
def get_commands():
  devices = [ ]
  a = Command('AAA', [ FuxApp, BuxApp ] )
  b = Command('BBB', [ FaxApp, QaxApp, ] )
  c = Command('CCC', [ FuxApp, BaxApp, QuxApp, BuxApp ] )
  return [ a, b, c ]

class GlobalOptions(object):
  def setup(self):
    print "setting up global options"
class Application(LoggingApp, GlobalOptions):
  """Test Hello World
  """
  name = "dispatcher"
  commands = { }

  def setup(self):
    # just after wrapping argument during __call__
    # !? or during __init__
    super(Application, self).setup( )
    GlobalOptions.setup(self)
    self.add_param("bar", help="fake option", action='store_true')
    self.subparsers = self.argparser.add_subparsers(dest='command', help='fake help on this command')

    for dev in get_commands():
      self.add_command( dev )

  def pre_run(self):
    # called just before main, updates params, parses args
    super(Application, self).pre_run()

  def add_command(self, command):
    self.commands[command.name] = command
    parser = self.subparsers.add_parser(command.name, help=command.help())
    #parser.set_defaults(run=self.main)
    command.setup(parser)

  def main(self):
    self.log.warn("hello world warn")
    self.log.debug("hello world debug")
    self.log.info("hello world info")
    self.log.error("hello world error")
    self.log.critical("hello world critical")
    self.log.fatal("hello world fatal")

    command  = self.commands[self.params.command]
    pprint(self.params)
    command.main(self)
    

if __name__ == '__main__':
  app = Application()
  app.run( )

#####
# EOF
Using pyCLI to create some commands and subcommands.