mirror of
https://github.com/datafolklabs/cement.git
synced 2026-02-06 13:56:49 +00:00
Further Refactor Issue #205
This commit is contained in:
parent
f9f30c2c33
commit
3dba8388b8
7
Vagrantfile
vendored
7
Vagrantfile
vendored
@ -6,6 +6,13 @@ Vagrant.configure("2") do |config|
|
||||
this.vm.provision "shell", inline: "/vagrant/scripts/vagrant/up.sh"
|
||||
end
|
||||
|
||||
config.vm.define "ubuntu-12.04", primary: true do |this|
|
||||
this.vm.box = "ubuntu-12.04"
|
||||
this.vm.hostname = "ubuntu-12.04"
|
||||
this.vm.box_url = "https://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-amd64-vagrant-disk1.box"
|
||||
this.vm.provision "shell", inline: "/vagrant/scripts/vagrant/up.sh"
|
||||
end
|
||||
|
||||
config.vm.provider "virtualbox" do |vb|
|
||||
vb.memory = 1024
|
||||
vb.cpus = 2
|
||||
|
||||
@ -967,14 +967,12 @@ class CementApp(meta.MetaMixin):
|
||||
for handler_class in self._meta.handlers:
|
||||
handler.register(handler_class)
|
||||
|
||||
def _pre_parse_args(self):
|
||||
def _parse_args(self):
|
||||
for res in hook.run('pre_argument_parsing', self):
|
||||
pass
|
||||
|
||||
def _parse_args(self):
|
||||
self._parsed_args = self.args.parse(self.argv)
|
||||
|
||||
def _post_parse_args(self):
|
||||
|
||||
if self._meta.arguments_override_config is True:
|
||||
for member in dir(self._parsed_args):
|
||||
if member and member.startswith('_'):
|
||||
@ -1174,6 +1172,7 @@ class CementApp(meta.MetaMixin):
|
||||
self.args = self._resolve_handler('argument',
|
||||
self._meta.argument_handler)
|
||||
self.args.prog = self._meta.label
|
||||
|
||||
self.args.add_argument('--debug', dest='debug',
|
||||
action='store_true',
|
||||
help='toggle debug output')
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
import re
|
||||
import argparse
|
||||
import sys
|
||||
from argparse import ArgumentParser
|
||||
from ..core import backend, arg, handler, hook
|
||||
from ..core.controller import IController
|
||||
@ -69,13 +70,12 @@ class expose(object):
|
||||
Used to expose controller functions to be listed as commands, and to
|
||||
decorate the function with Meta data for the argument parser.
|
||||
|
||||
:param help: Help text to display for that command.
|
||||
:type help: str
|
||||
:param hide: Whether the command should be visible.
|
||||
:type hide: boolean
|
||||
:param aliases: Aliases to this command.
|
||||
command/function label.
|
||||
:type aliases: list
|
||||
:param arguments: List of tuples that define arguments to add to this
|
||||
command sub-parser.
|
||||
:keyword parser_options: Additional options to pass to ArgParse.
|
||||
:type parser_options: dict
|
||||
|
||||
Usage:
|
||||
|
||||
@ -87,11 +87,19 @@ class expose(object):
|
||||
class Meta:
|
||||
label = 'base'
|
||||
|
||||
@expose(hide=True, aliases=['run'])
|
||||
# Note: Default functions only work on Python 3.4+
|
||||
@expose(hide=True)
|
||||
def default(self):
|
||||
print("In MyAppBaseController.default()")
|
||||
|
||||
@expose()
|
||||
@expose(
|
||||
help='this is the help message for my_command',
|
||||
aliases=['my_cmd'], # only available in Python 3+
|
||||
arguments=[
|
||||
(['-f', '--foo'],
|
||||
dict(help='foo option', action='store', dest='foo')),
|
||||
]
|
||||
)
|
||||
def my_command(self):
|
||||
print("In MyAppBaseController.my_command()")
|
||||
|
||||
@ -170,7 +178,8 @@ class ArgparseController(handler.CementBaseHandler):
|
||||
#: The string identifier for the controller.
|
||||
label = 'base'
|
||||
|
||||
#: A list of aliases for the controller/sub-parser.
|
||||
#: A list of aliases for the controller/sub-parser. **Only available
|
||||
#: in Python 3+.
|
||||
aliases = []
|
||||
|
||||
#: A config [section] to merge config_defaults into. Cement will
|
||||
@ -245,6 +254,10 @@ class ArgparseController(handler.CementBaseHandler):
|
||||
Function to call if no sub-command is passed. Note that this can
|
||||
**not** start with an ``_`` due to backward compatibility restraints
|
||||
in how Cement discovers and maps commands.
|
||||
|
||||
Note: Currently, default function/sub-command only functions on
|
||||
Python 3.4+. Previous versions of Python/ArgParse will throw the
|
||||
exception ``error: too few arguments``.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
@ -346,8 +359,10 @@ class ArgparseController(handler.CementBaseHandler):
|
||||
def _get_parser_options(self, contr):
|
||||
kwargs = contr._meta.parser_options.copy()
|
||||
|
||||
if 'aliases' not in kwargs.keys():
|
||||
kwargs['aliases'] = contr._meta.aliases
|
||||
if sys.version_info[0] > 3:
|
||||
if 'aliases' not in kwargs.keys():
|
||||
kwargs['aliases'] = contr._meta.aliases
|
||||
|
||||
if 'description' not in kwargs.keys():
|
||||
kwargs['description'] = contr._meta.description
|
||||
if 'usage' not in kwargs.keys():
|
||||
@ -403,6 +418,9 @@ class ArgparseController(handler.CementBaseHandler):
|
||||
kwargs = self._get_subparser_options(self)
|
||||
sub = self.app.args.add_subparsers(**kwargs)
|
||||
parents['base'] = sub
|
||||
base_parser_options = self._get_parser_options(self)
|
||||
for key,val in base_parser_options.items():
|
||||
setattr(self.app.args, key, val)
|
||||
|
||||
# and if only base controller registered... go ahead and return
|
||||
if len(handler.list('controller')) <= 1:
|
||||
@ -442,6 +460,13 @@ class ArgparseController(handler.CementBaseHandler):
|
||||
kwargs = self._get_subparser_options(contr)
|
||||
parents[label] = parsers[label].add_subparsers(**kwargs)
|
||||
|
||||
parsers[label].add_argument('__controller__',
|
||||
action='store',
|
||||
default=contr._meta.label,
|
||||
nargs='?',
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
|
||||
# if it's embedded, then just set the use the same as the
|
||||
# controller its stacked on
|
||||
elif stacked_type == 'embedded':
|
||||
@ -503,41 +528,75 @@ class ArgparseController(handler.CementBaseHandler):
|
||||
|
||||
commands = controller._collect_commands()
|
||||
for command in commands:
|
||||
# FIX ME: this is confusting... prob need one for controller, one for
|
||||
# commands
|
||||
kwargs = self._get_command_parser_options(command)
|
||||
|
||||
func_name = command['func_name']
|
||||
LOG.debug("adding command '%s' " % command['label'] + \
|
||||
"(controller=%s, func=%s)" % \
|
||||
(controller._meta.label, func_name))
|
||||
"(controller=%s, func=%s)" % \
|
||||
(controller._meta.label, func_name))
|
||||
|
||||
cmd_parent = self._get_parser_parent_by_controller(controller)
|
||||
command_parser = cmd_parent.add_parser(command['label'], **kwargs)
|
||||
|
||||
# can't call self inside the CustomAction
|
||||
_controllers = self._controllers
|
||||
#_controllers = self._controllers
|
||||
|
||||
class CustomAction(argparse.Action):
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
func_name = _clean_command_func(namespace.command)
|
||||
command['controller'].app._parsed_args = namespace
|
||||
### FIX ME: This Works on Python 3.3, but not on Python 3.4
|
||||
# class BadCustomAction(argparse.Action):
|
||||
# def __call__(self, parser, namespace, values, option_string=None):
|
||||
# func_name = _clean_command_func(namespace.command)
|
||||
# command['controller'].app._parsed_args = namespace
|
||||
|
||||
# app._pre_parse_args() happends in _dispace
|
||||
# # app._pre_parse_args() happends in _dispatch
|
||||
|
||||
# let all controllers process arguments
|
||||
for contr in _controllers:
|
||||
contr._process_parsed_arguments()
|
||||
# # let all controllers process arguments
|
||||
# for contr in _controllers:
|
||||
# contr._process_parsed_arguments()
|
||||
|
||||
command['controller'].app._post_parse_args()
|
||||
# command['controller'].app._post_parse_args()
|
||||
|
||||
# func = getattr(command['controller'], func_name)
|
||||
# func()
|
||||
# setattr(namespace, self.dest, values)
|
||||
|
||||
# command_parser.add_argument('__controller__',
|
||||
# action=CustomAction,
|
||||
# nargs='?',
|
||||
# help=argparse.SUPPRESS,
|
||||
# )
|
||||
|
||||
|
||||
# class CustomAction(argparse.Action):
|
||||
# def __call__(self, parser, namespace, values, option_string=None):
|
||||
# print("Namespace > %s" % namespace)
|
||||
# print("Values > %s" % values)
|
||||
|
||||
# func_name = _clean_command_func(namespace.command)
|
||||
# command['controller'].app._parsed_args = namespace
|
||||
|
||||
# # app._pre_parse_args() happends in _dispatch
|
||||
|
||||
# # let all controllers process arguments
|
||||
# for contr in _controllers:
|
||||
# contr._process_parsed_arguments()
|
||||
|
||||
# command['controller'].app._post_parse_args()
|
||||
|
||||
# func = getattr(command['controller'], func_name)
|
||||
# func()
|
||||
# setattr(namespace, self.dest, values)
|
||||
|
||||
func = getattr(command['controller'], func_name)
|
||||
func()
|
||||
setattr(namespace, self.dest, values)
|
||||
|
||||
# create a default command for the parser (cluster fuck)
|
||||
command_parser.add_argument('__controller__',
|
||||
action=CustomAction,
|
||||
action='store',
|
||||
default=command['controller']._meta.label,
|
||||
nargs='?',
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
command_parser.add_argument('command',
|
||||
action='store',
|
||||
default=command['label'],
|
||||
nargs='?',
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
@ -560,14 +619,14 @@ class ArgparseController(handler.CementBaseHandler):
|
||||
|
||||
def _collect_arguments(self):
|
||||
LOG.debug("collecting arguments from %s " % self +
|
||||
"(stacked_on='%s', stacked_type='%s')" % \
|
||||
(self._meta.stacked_on, self._meta.stacked_type))
|
||||
"(stacked_on='%s', stacked_type='%s')" % \
|
||||
(self._meta.stacked_on, self._meta.stacked_type))
|
||||
return self._meta.arguments
|
||||
|
||||
def _collect_commands(self):
|
||||
LOG.debug("collecting commands from %s " % self +
|
||||
"(stacked_on='%s', stacked_type='%s')" % \
|
||||
(self._meta.stacked_on, self._meta.stacked_type))
|
||||
"(stacked_on='%s', stacked_type='%s')" % \
|
||||
(self._meta.stacked_on, self._meta.stacked_type))
|
||||
|
||||
commands = []
|
||||
for member in dir(self.__class__):
|
||||
@ -589,30 +648,39 @@ class ArgparseController(handler.CementBaseHandler):
|
||||
self._process_arguments(contr)
|
||||
self._process_commands(contr)
|
||||
|
||||
for res in hook.run('pre_argument_parsing', self):
|
||||
pass
|
||||
|
||||
self.app._pre_parse_args()
|
||||
self.app._parse_args()
|
||||
|
||||
if not hasattr(self.app.pargs, '__controller__'):
|
||||
# this happens in the CustomAction if __controller__ is set
|
||||
for res in hook.run('pre_argument_parsing', self):
|
||||
pass
|
||||
for contr in self._controllers:
|
||||
contr._process_parsed_arguments()
|
||||
|
||||
if self.app.pargs.command is None:
|
||||
# no sub-command was passed, so we can assume default
|
||||
func_name = _clean_command_func(self._meta.default_func)
|
||||
func = getattr(self, func_name)
|
||||
func()
|
||||
if hasattr(self.app.pargs, '__controller__'):
|
||||
if self.app.pargs.__controller__ == 'base':
|
||||
contr = self
|
||||
else:
|
||||
# then this is the name of the controller given as a
|
||||
# sub-command
|
||||
contr = handler.get('controller', self.app.pargs.command)()
|
||||
# FIX ME: Create a dict after self._controllers is setup so
|
||||
# that we can just call the controller from there (already
|
||||
# setup)
|
||||
contr = handler.get('controller',
|
||||
self.app.pargs.__controller__)()
|
||||
contr._setup(self.app)
|
||||
func_name = _clean_command_func(contr._meta.default_func)
|
||||
func = getattr(contr, func_name)
|
||||
func()
|
||||
|
||||
else:
|
||||
# if no __controller__ is set then assume base controller
|
||||
contr = self
|
||||
|
||||
|
||||
if self.app.pargs.command is None:
|
||||
func_name = _clean_command_func(contr._meta.default_func)
|
||||
else:
|
||||
func_name = _clean_command_func(self.app.pargs.command)
|
||||
|
||||
if hasattr(contr, func_name):
|
||||
func = getattr(contr, func_name)
|
||||
func()
|
||||
else:
|
||||
self.app.log.fatal(
|
||||
"Controller function does not exist " + \
|
||||
"%s.%s()" % (contr.__class__, func_name))
|
||||
|
||||
|
||||
def load(app):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user