Changeset - 9694902d4cdd
[Not reviewed]
0 2 0
Lance Edgar - 9 years ago 2015-08-16 19:36:40
ledgar@sacfoodcoop.com
Remove some unused/unwanted command line arguments.

These weren't bad ideas, but hadn't really been implemented. Easier just
to get rid of them for now.
2 files changed with 1 insertions and 32 deletions:
0 comments (0 inline, 0 general)
rattail/commands.py
Show inline comments
 
@@ -75,49 +75,49 @@ def date_argument(string):
 
    """
 
    try:
 
        date = datetime.datetime.strptime(string, '%Y-%m-%d').date()
 
    except ValueError:
 
        raise argparse.ArgumentTypeError("Date must be in YYYY-MM-DD format")
 
    return date
 

	
 

	
 
class Command(object):
 
    """
 
    The primary command for the application.
 

	
 
    This effectively *is* the ``rattail`` console application.  It mostly
 
    provides the structure for subcommands, which really do all the work.
 

	
 
    This command is designed to be subclassed, should your application need
 
    similar functionality.
 
    """
 
    name = 'rattail'
 
    version = __version__
 
    description = "Retail Software Framework"
 
    long_description = """
 
Rattail is a retail software framework.
 

	
 
Copyright (c) 2010-2012 Lance Edgar <lance@edbob.org>
 
Copyright (c) 2010-2015 Lance Edgar <lance@edbob.org>
 

	
 
This program comes with ABSOLUTELY NO WARRANTY.  This is free software,
 
and you are welcome to redistribute it under certain conditions.
 
See the file COPYING.txt for more information.
 
"""
 

	
 
    stdout = sys.stdout
 
    stderr = sys.stderr
 

	
 
    def __init__(self):
 
        self.subcommands = load_entry_points('{0}.commands'.format(self.name))
 

	
 
    def __unicode__(self):
 
        return unicode(self.name)
 

	
 
    @property
 
    def db_config_section(self):
 
        """
 
        Name of section in config file which should have database connection
 
        info.  This defaults to ``'rattail.db'`` but may be overridden so the
 
        command framework can sit in front of a non-Rattail database if needed.
 

	
 
        This is used to auto-configure a "default" database engine for the app,
 
        when any command is invoked.
 
@@ -160,116 +160,103 @@ Options:
 
  -d, --debug       Increase logging level to DEBUG
 
  -P, --progress    Show progress indicators (where relevant)
 
  -v, --verbose     Increase logging level to INFO
 
  -V, --version     Display program version and exit
 

	
 
Commands:\n""".format(self.description, self.name))
 

	
 
        for cmd in self.iter_subcommands():
 
            self.stdout.write("  {0:<16s}  {1}\n".format(cmd.name, cmd.description))
 

	
 
        self.stdout.write("\nTry '{0} help <command>' for more help.\n".format(self.name))
 

	
 
    def run(self, *args):
 
        """
 
        Parse command line arguments and execute appropriate subcommand.
 
        """
 
        parser = ArgumentParser(
 
            prog=self.name,
 
            description=self.description,
 
            add_help=False,
 
            )
 

	
 
        parser.add_argument('-c', '--config', action='append', dest='config_paths',
 
                            metavar='PATH')
 
        parser.add_argument('-d', '--debug', action='store_true', dest='debug')
 
        parser.add_argument('-n', '--no-init', action='store_true', default=False)
 
        parser.add_argument('-P', '--progress', action='store_true', default=False)
 
        parser.add_argument('--stdout', metavar='PATH', type=argparse.FileType('w'),
 
                            help="Optional path to which STDOUT should be effectively redirected.")
 
        parser.add_argument('--stderr', metavar='PATH', type=argparse.FileType('w'),
 
                            help="Optional path to which STDERR should be effectively redirected.")
 
        parser.add_argument('-v', '--verbose', action='store_true', dest='verbose')
 
        parser.add_argument('-V', '--version', action='version',
 
                            version="%(prog)s {0}".format(self.version))
 
        parser.add_argument('command', nargs='*')
 

	
 
        # Parse args and determine subcommand.
 
        args = parser.parse_args(list(args))
 
        if not args or not args.command:
 
            self.print_help()
 
            return
 

	
 
        # Show (sub)command help if so instructed, or unknown subcommand.
 
        cmd = args.command.pop(0)
 
        if cmd == 'help':
 
            if len(args.command) != 1:
 
                self.print_help()
 
                return
 
            cmd = args.command[0]
 
            if cmd not in self.subcommands:
 
                self.print_help()
 
                return
 
            cmd = self.subcommands[cmd](parent=self)
 
            cmd.parser.print_help()
 
            return
 
        elif cmd not in self.subcommands:
 
            self.print_help()
 
            return
 

	
 
        # Okay, we should be done needing to print help messages.  Now it's
 
        # safe to redirect STDOUT/STDERR, if necessary.
 
        if args.stdout:
 
            self.stdout = args.stdout
 
        if args.stderr:
 
            self.stderr = args.stderr
 

	
 
        # Basic logging should be established before init()ing.
 

	
 
        # Use root logger if setting logging flags.
 
        log = logging.getLogger()
 

	
 
        # TODO: Figure out the basic logging pattern we're after here.
 
        # edbob.basic_logging()
 
        logging.basicConfig()
 

	
 
        if args.verbose:
 
            log.setLevel(logging.INFO)
 
        if args.debug:
 
            log.setLevel(logging.DEBUG)
 

	
 
        # Initialize everything...
 
        config = None
 
        if not args.no_init:
 
            edbob.init(self.name, *(args.config_paths or []))
 
            config = RattailConfig(edbob.config)
 

	
 
            # Command line logging flags should override config.
 
            if args.verbose:
 
                log.setLevel(logging.INFO)
 
            if args.debug:
 
                log.setLevel(logging.DEBUG)
 

	
 
            # Configure the default database engine.
 
            try:
 
                from rattail.db.util import configure_session_factory
 
            except ImportError:
 
                pass            # assume no sqlalchemy
 
            else:
 
                configure_session_factory(config, section=self.db_config_section,
 
                                          session_factory=self.db_session_factory)
 

	
 
                # Maybe configure Continuum versioning.
 
                if (self.db_config_section == 'rattail.db'
 
                    and config.getboolean('rattail.db', 'versioning.enabled')):
 
                    from rattail.db.continuum  import configure_versioning
 
                    configure_versioning(config)
 

	
 
        # And finally, do something of real value...
 
        cmd = self.subcommands[cmd](self)
 
        cmd.config = config
 
        cmd.show_progress = args.progress
 
        cmd.progress = Progress if args.progress else None
 
        cmd._run(*(args.command + args.argv))
 

	
 

	
 
class Subcommand(object):
tests/test_commands.py
Show inline comments
 
@@ -113,66 +113,48 @@ class TestCommand(TestCase):
 
                self.stdout.flush()
 
        command = commands.Command()
 
        fake = command.subcommands['fake'] = Fake
 
        tmp = TempIO()
 
        config_path = tmp.putfile('test.ini', '')
 
        out_path = tmp.putfile('out.txt', '')
 
        command.run('fake', '--config', config_path, '--stdout', out_path)
 
        with open(out_path) as f:
 
            self.assertEqual(f.read(), "standard output stuff")
 

	
 
    def test_stderr_may_be_redirected(self):
 
        class Fake(commands.Subcommand):
 
            def run(self, args):
 
                self.stderr.write("standard error stuff")
 
                self.stderr.flush()
 
        command = commands.Command()
 
        fake = command.subcommands['fake'] = Fake
 
        tmp = TempIO()
 
        config_path = tmp.putfile('test.ini', '')
 
        err_path = tmp.putfile('err.txt', '')
 
        command.run('fake', '--config', config_path, '--stderr', err_path)
 
        with open(err_path) as f:
 
            self.assertEqual(f.read(), "standard error stuff")
 

	
 
    def test_verbose_flag_sets_root_logging_level_to_info(self):
 
        self.assertEqual(logging.getLogger().getEffectiveLevel(), logging.NOTSET)
 
        tmp = TempIO()
 
        config_path = tmp.putfile('test.ini', '')
 
        command = commands.Command()
 
        fake = command.subcommands['fake'] = Mock()
 
        command.run('fake', '--config', config_path, '--verbose')
 
        self.assertEqual(logging.getLogger().getEffectiveLevel(), logging.INFO)
 

	
 
    def test_debug_flag_sets_root_logging_level_to_debug(self):
 
        self.assertEqual(logging.getLogger().getEffectiveLevel(), logging.NOTSET)
 
        tmp = TempIO()
 
        config_path = tmp.putfile('test.ini', '')
 
        command = commands.Command()
 
        fake = command.subcommands['fake'] = Mock()
 
        command.run('fake', '--config', config_path, '--debug')
 
        self.assertEqual(logging.getLogger().getEffectiveLevel(), logging.DEBUG)
 

	
 
    def test_noinit_flag_means_no_config(self):
 
        command = commands.Command()
 
        fake = command.subcommands['fake'] = Mock()
 
        command.run('fake', '--no-init')
 
        self.assertTrue(fake.return_value.config is None)
 

	
 

	
 
class TestSubcommand(TestCase):
 

	
 
    def test_repr(self):
 
        command = commands.Command()
 
        subcommand = commands.Subcommand(command)
 
        subcommand.name = 'fake-command'
 
        self.assertEqual(repr(subcommand), "Subcommand(name=u'fake-command')")
 

	
 
    def test_add_parser_args_does_nothing(self):
 
        command = commands.Command()
 
        subcommand = commands.Subcommand(command)
 
        # Not sure this is really the way to test this, but...
 
        self.assertEqual(len(subcommand.parser._action_groups[0]._actions), 1)
 
        subcommand.add_parser_args(subcommand.parser)
 
        self.assertEqual(len(subcommand.parser._action_groups[0]._actions), 1)
 

	
 
    def test_run_not_implemented(self):
0 comments (0 inline, 0 general)