@@ -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) | |||
# |
@@ -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) |
@@ -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 |