[enh] Allow to define global abstract arguments in the cli

This commit is contained in:
Jérôme Lebleu 2015-11-13 11:53:31 +01:00
parent 28db3c5d37
commit 013447bbe7
5 changed files with 45 additions and 18 deletions

View file

@ -94,7 +94,8 @@ def api(namespaces, host='localhost', port=80, routes={},
'use_cache': use_cache })
moulinette.run(host, port)
def cli(namespaces, args, print_json=False, print_plain=False, use_cache=True):
def cli(namespaces, args, print_json=False, print_plain=False, use_cache=True,
parser_kwargs={}):
"""Command line interface
Execute an action with the moulinette from the CLI and print its
@ -107,12 +108,18 @@ def cli(namespaces, args, print_json=False, print_plain=False, use_cache=True):
- print_plain -- True to print result as a script-usable string
- use_cache -- False if it should parse the actions map file
instead of using the cached one
- parser_kwargs -- A dict of arguments to pass to the parser
class at construction
"""
try:
moulinette = init_interface('cli',
actionsmap={'namespaces': namespaces,
'use_cache': use_cache})
actionsmap={
'namespaces': namespaces,
'use_cache': use_cache,
'parser_kwargs': parser_kwargs,
},
)
moulinette.run(args, print_json, print_plain)
except MoulinetteError as e:
import logging

View file

@ -342,17 +342,20 @@ class ActionsMap(object):
all available namespaces.
Keyword arguments:
- parser -- The BaseActionsMapParser derived class to use for
parsing the actions map
- parser_class -- The BaseActionsMapParser derived class to use
for parsing the actions map
- namespaces -- The list of namespaces to use
- use_cache -- False if it should parse the actions map file
instead of using the cached one.
instead of using the cached one
- parser_kwargs -- A dict of arguments to pass to the parser
class at construction
"""
def __init__(self, parser, namespaces=[], use_cache=True):
if not issubclass(parser, BaseActionsMapParser):
raise ValueError("Invalid parser class '%s'" % parser.__name__)
self._parser_class = parser
def __init__(self, parser_class, namespaces=[], use_cache=True,
parser_kwargs={}):
if not issubclass(parser_class, BaseActionsMapParser):
raise ValueError("Invalid parser class '%s'" % parser_class.__name__)
self.parser_class = parser_class
self.use_cache = use_cache
if len(namespaces) == 0:
@ -380,8 +383,8 @@ class ActionsMap(object):
m18n.load_namespace(n)
# Generate parsers
self.extraparser = ExtraArgumentParser(parser.interface)
self._parser = self._construct_parser(actionsmaps)
self.extraparser = ExtraArgumentParser(parser_class.interface)
self._parser = self._construct_parser(actionsmaps, **parser_kwargs)
@property
def parser(self):
@ -515,13 +518,15 @@ class ActionsMap(object):
## Private methods
def _construct_parser(self, actionsmaps):
def _construct_parser(self, actionsmaps, **kwargs):
"""
Construct the parser with the actions map
Keyword arguments:
- actionsmaps -- A dict of multi-level dictionnary of
categories/actions/arguments list for each namespaces
- **kwargs -- Additionnal arguments to pass at the parser
class instantiation
Returns:
An interface relevant's parser object
@ -551,7 +556,7 @@ class ActionsMap(object):
parser.add_argument(*names, **argp)
# Instantiate parser
top_parser = self._parser_class()
top_parser = self.parser_class(**kwargs)
# Iterate over actions map namespaces
for n, actionsmap in actionsmaps.items():

View file

@ -31,7 +31,7 @@ class BaseActionsMapParser(object):
- parent -- A parent BaseActionsMapParser derived object
"""
def __init__(self, parent=None):
def __init__(self, parent=None, **kwargs):
if parent:
self._o = parent
else:

View file

@ -476,7 +476,7 @@ class ActionsMapParser(BaseActionsMapParser):
the arguments is represented by a ExtendedArgumentParser object.
"""
def __init__(self, parent=None):
def __init__(self, parent=None, **kwargs):
super(ActionsMapParser, self).__init__(parent)
self._parsers = {} # dict({(method, path): _HTTPArgumentParser})

View file

@ -5,6 +5,7 @@ import sys
import errno
import getpass
import locale
from argparse import SUPPRESS
from moulinette.core import MoulinetteError
from moulinette.interfaces import (
@ -172,9 +173,12 @@ class ActionsMapParser(BaseActionsMapParser):
Keyword arguments:
- parser -- The ExtendedArgumentParser object to use
- subparser_kwargs -- Arguments to pass to the sub-parser group
- top_parser -- An ArgumentParser object whose arguments should
be take into account but not parsed
"""
def __init__(self, parent=None, parser=None, subparser_kwargs=None):
def __init__(self, parent=None, parser=None, subparser_kwargs=None,
top_parser=None, **kwargs):
super(ActionsMapParser, self).__init__(parent)
if subparser_kwargs is None:
@ -182,6 +186,14 @@ class ActionsMapParser(BaseActionsMapParser):
self._parser = parser or ExtendedArgumentParser()
self._subparsers = self._parser.add_subparsers(**subparser_kwargs)
self._global_parser = parent._global_parser if parent else None
if top_parser:
# Append each top parser action to the global group
glob = self.add_global_parser()
for action in top_parser._actions:
action.dest = SUPPRESS
glob._add_action(action)
## Implement virtual properties
@ -198,7 +210,10 @@ class ActionsMapParser(BaseActionsMapParser):
return [name]
def add_global_parser(self, **kwargs):
return self._parser.add_mutually_exclusive_group()
if not self._global_parser:
self._global_parser = self._parser.add_argument_group(
"global arguments")
return self._global_parser
def add_category_parser(self, name, category_help=None, **kwargs):
"""Add a parser for a category