Browse Source

Refactored commando to its own package

main
Lakshmi Vyasarajan 14 years ago
parent
commit
eef93da110
3 changed files with 0 additions and 236 deletions
  1. +0
    -28
      hyde/cli.py
  2. +0
    -113
      hyde/commando.py
  3. +0
    -95
      hyde/tests/test_commando.py

+ 0
- 28
hyde/cli.py View File

@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
"""
The command line interface for hyde.
"""
import argparse
from version import __version__
from engine import init, gen, serve


def main():
"""
The main function called by hyde executable
"""
# parser = argparse.ArgumentParser(description='hyde - a python static website generator',
# epilog='Use %(prog)s {command} -h to get help on individual commands')
# parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + __version__)
# parser.add_argument('-s', '--sitepath', action='store', default='.', help="Location of the hyde site")
# subcommands = parser.add_subparsers(title="Hyde commands",
# description="Entry points for hyde")
# init_command = subcommands.add_parser('init', help='Create a new hyde site')
# init_command.set_defaults(run=init)
# init_command.add_argument('-t', '--template', action='store', default='basic', dest='template',
# help='Overwrite the current site if it exists')
# init_command.add_argument('-f', '--force', action='store_true', default=False, dest='force',
# help='Overwrite the current site if it exists')
# args = parser.parse_args()
# args.run(args)
#

+ 0
- 113
hyde/commando.py View File

@@ -1,113 +0,0 @@
# -*- coding: utf-8 -*-
"""
Declarative interface for argparse
"""
from argparse import ArgumentParser
from collections import namedtuple

__all__ = [
'command',
'subcommand',
'param',
'Application'
]

class CommandLine(type):
"""
Meta class that enables declarative command definitions
"""
def __new__(mcs, name, bases, attrs):
instance = super(CommandLine, mcs).__new__(mcs, name, bases, attrs)
subcommands = []
main_command = None
for name, member in attrs.iteritems():
if hasattr(member, "command"):
main_command = member
elif hasattr(member, "subcommand"):
subcommands.append(member)
main_parser = None
def add_arguments(parser, params):
"""
Adds parameters to the parser
"""
for parameter in params:
parser.add_argument(*parameter.args, **parameter.kwargs)
if main_command:
main_parser = ArgumentParser(*main_command.command.args, **main_command.command.kwargs)
add_arguments(main_parser, main_command.params)
subparsers = None
if len(subcommands):
subparsers = main_parser.add_subparsers()
for sub in subcommands:
parser = subparsers.add_parser(*sub.subcommand.args, **sub.subcommand.kwargs)
parser.set_defaults(run=sub)
add_arguments(parser, sub.params)

instance.__parser__ = main_parser
instance.__main__ = main_command
return instance

values = namedtuple('__meta_values', 'args, kwargs')
class metarator(object):
"""
A generic decorator that tags the decorated method with
the passed in arguments for meta classes to process them.
"""
def __init__(self, *args, **kwargs):
self.values = values._make((args, kwargs))

def metarate(self, func, name='values'):
"""
Set the values object to the function object's namespace
"""
setattr(func, name, self.values)
return func

def __call__(self, func):
return self.metarate(func)


class command(metarator):
"""
Used to decorate the main entry point
"""
def __call__(self, func):
return self.metarate(func, name='command')

class subcommand(metarator):
"""
Used to decorate the subcommands
"""
def __call__(self, func):
return self.metarate(func, name='subcommand')

class param(metarator):
"""
Use this decorator instead of `ArgumentParser.add_argument`.
"""
def __call__(self, func):
func.params = func.params if hasattr(func, 'params') else []
func.params.append(self.values)
return func


class Application(object):
"""
Barebones base class for command line applications.
"""
__metaclass__ = CommandLine

def parse(self, argv):
"""
Simple method that delegates to the ArgumentParser
"""
return self.__parser__.parse_args(argv)

def run(self, args):
"""
Runs the main command or sub command based on user input
"""
if hasattr(args, 'run'):
args.run(self, args)
else:
self.__main__(args)

+ 0
- 95
hyde/tests/test_commando.py View File

@@ -1,95 +0,0 @@
# -*- coding: utf-8 -*-
"""
Use nose
`$ pip install nose`
`$ nosetests`
"""

from contextlib import nested
from hyde.commando import Application, command, subcommand, param
from util import trap_exit_pass, trap_exit_fail
from mock import Mock, patch
try:
import cStringIO as StringIO
except ImportError:
import StringIO

import sys

class BasicCommandLine(Application):

@command(description='test', prog='Basic')
@param('--force', action='store_true', dest='force1')
@param('--force2', action='store', dest='force2')
@param('--version', action='version', version='%(prog)s 1.0')
def main(self, params):
assert params.force1 == eval(params.force2)
self._main()

def _main(): pass


@trap_exit_fail
def test_command_basic():

with patch.object(BasicCommandLine, '_main') as _main:
c = BasicCommandLine()
args = c.parse(['--force', '--force2', 'True'])
c.run(args)
assert _main.call_count == 1

args = c.parse(['--force2', 'False'])
c.run(args)

assert _main.call_count == 2


def test_command_version():
with patch.object(BasicCommandLine, '_main') as _main:
c = BasicCommandLine()
exception = False
try:
c.parse(['--version'])
assert False
except SystemExit:
exception = True
assert exception
assert not _main.called

class ComplexCommandLine(Application):

@command(description='test', prog='Complex')
@param('--force', action='store_true', dest='force1')
@param('--force2', action='store', dest='force2')
@param('--version', action='version', version='%(prog)s 1.0')
def main(self, params):
assert params.force1 == eval(params.force2)
self._main()

@subcommand('sub', description='test')
@param('--launch', action='store_true', dest='launch1')
@param('--launch2', action='store', dest='launch2')
def sub(self, params):
assert params.launch1 == eval(params.launch2)
self._sub()

def _main(): pass
def _sub(): pass


@trap_exit_pass
def test_command_subcommands_usage():
with nested(patch.object(ComplexCommandLine, '_main'),
patch.object(ComplexCommandLine, '_sub')) as (_main, _sub):
c = ComplexCommandLine()
c.parse(['--usage'])

@trap_exit_fail
def test_command_subcommands():
with nested(patch.object(ComplexCommandLine, '_main'),
patch.object(ComplexCommandLine, '_sub')) as (_main, _sub):
c = ComplexCommandLine()
args = c.parse(['sub', '--launch', '--launch2', 'True'])
c.run(args)
assert not _main.called
assert _sub.call_count == 1

Loading…
Cancel
Save