mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
Merge branch 'unstable' into support-subcategories
Conflicts: moulinette/actionsmap.py
This commit is contained in:
commit
0bbd47c090
9 changed files with 100 additions and 61 deletions
|
@ -570,31 +570,10 @@ class ActionsMap(object):
|
|||
|
||||
"""
|
||||
# Get extra parameters
|
||||
if not self.use_cache:
|
||||
validate_extra = True
|
||||
else:
|
||||
if self.use_cache:
|
||||
validate_extra = False
|
||||
|
||||
# Add arguments to the parser
|
||||
def _add_arguments(tid, parser, arguments):
|
||||
# parser is argparse._ArgumentGroup for top_parser
|
||||
# or ExtendedArgumentParser for other cases
|
||||
# or maybe something else?
|
||||
for argument_name, argument_options in arguments.items():
|
||||
# will adapt arguments name for cli or api context
|
||||
names = top_parser.format_arg_names(str(argument_name),
|
||||
argument_options.pop('full', None))
|
||||
|
||||
if "type" in argument_options:
|
||||
argument_options['type'] = eval(argument_options['type'])
|
||||
|
||||
if "extra" not in argument_options:
|
||||
parser.add_argument(*names, **argument_options)
|
||||
continue
|
||||
|
||||
extra = argument_options.pop('extra')
|
||||
argument_dest = parser.add_argument(*names, **argument_options).dest
|
||||
self.extraparser.add_argument(tid, argument_dest, extra, validate_extra)
|
||||
else:
|
||||
validate_extra = True
|
||||
|
||||
# Instantiate parser
|
||||
#
|
||||
|
@ -616,9 +595,7 @@ class ActionsMap(object):
|
|||
top_parser.set_global_conf(_global['configuration'])
|
||||
|
||||
if top_parser.has_global_parser():
|
||||
# GLOBAL_SECTION = '_global'
|
||||
_add_arguments(GLOBAL_SECTION, top_parser.global_parser,
|
||||
_global['arguments'])
|
||||
top_parser.add_global_arguments(_global['arguments'])
|
||||
|
||||
# category_name is stuff like "user", "domain", "hooks"...
|
||||
# category_values is the values of this category (like actions)
|
||||
|
@ -635,7 +612,8 @@ class ActionsMap(object):
|
|||
subcategories = {}
|
||||
|
||||
# Get category parser
|
||||
category_parser = top_parser.add_category_parser(category_name, **category_values)
|
||||
category_parser = top_parser.add_category_parser(category_name,
|
||||
**category_values)
|
||||
|
||||
# action_name is like "list" of "domain list"
|
||||
# action_options are the values
|
||||
|
@ -643,20 +621,23 @@ class ActionsMap(object):
|
|||
arguments = action_options.pop('arguments', {})
|
||||
tid = (namespace, category_name, action_name)
|
||||
|
||||
try:
|
||||
# Get action parser
|
||||
action_parser = category_parser.add_action_parser(action_name, tid, **action_options)
|
||||
except AttributeError:
|
||||
# No parser for the action
|
||||
action_parser = category_parser.add_action_parser(action_name,
|
||||
tid,
|
||||
**action_options)
|
||||
|
||||
if action_parser is None: # No parser for the action
|
||||
continue
|
||||
|
||||
# Store action identifier and add arguments
|
||||
action_parser.set_defaults(_tid=tid)
|
||||
_add_arguments(tid, action_parser, arguments)
|
||||
action_parser.add_arguments(arguments,
|
||||
extraparser=self.extraparser,
|
||||
format_arg_names=top_parser.format_arg_names,
|
||||
validate_extra=validate_extra)
|
||||
|
||||
if 'configuration' in action_options:
|
||||
configuration = action_options.pop('configuration')
|
||||
category_parser.set_conf(tid, configuration)
|
||||
category_parser.set_conf(tid, action_options['configuration'])
|
||||
|
||||
# subcategory_name is like "cert" in "domain cert status"
|
||||
# subcategory_values is the values of this subcategory (like actions)
|
||||
|
@ -682,12 +663,12 @@ class ActionsMap(object):
|
|||
|
||||
# Store action identifier and add arguments
|
||||
action_parser.set_defaults(_tid=tid)
|
||||
_add_arguments(tid, action_parser, arguments)
|
||||
action_parser.add_arguments(arguments,
|
||||
extraparser=self.extraparser,
|
||||
format_arg_names=top_parser.format_arg_names,
|
||||
validate_extra=validate_extra)
|
||||
|
||||
if 'configuration' in action_options:
|
||||
configuration = action_options.pop('configuration')
|
||||
subcategory_parser.set_conf(tid, configuration)
|
||||
|
||||
|
||||
category_parser.set_conf(tid, action_options['configuration'])
|
||||
|
||||
return top_parser
|
||||
|
|
|
@ -51,7 +51,7 @@ class BaseAuthenticator(object):
|
|||
# Virtual methods
|
||||
# Each authenticator classes must implement these methods.
|
||||
|
||||
def authenticate(password=None):
|
||||
def authenticate(self, password=None):
|
||||
"""Attempt to authenticate
|
||||
|
||||
Attempt to authenticate with given password. It should raise an
|
||||
|
|
|
@ -508,8 +508,8 @@ class _ExtendedSubParsersAction(argparse._SubParsersAction):
|
|||
class ExtendedArgumentParser(argparse.ArgumentParser):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ExtendedArgumentParser, self).__init__(
|
||||
formatter_class=PositionalsFirstHelpFormatter, *args, **kwargs)
|
||||
super(ExtendedArgumentParser, self).__init__(formatter_class=PositionalsFirstHelpFormatter,
|
||||
*args, **kwargs)
|
||||
|
||||
# Register additional actions
|
||||
self.register('action', 'callback', _CallbackAction)
|
||||
|
@ -541,6 +541,24 @@ class ExtendedArgumentParser(argparse.ArgumentParser):
|
|||
queue = list()
|
||||
return queue
|
||||
|
||||
def add_arguments(self, arguments, extraparser, format_arg_names=None, validate_extra=True):
|
||||
for argument_name, argument_options in arguments.items():
|
||||
# will adapt arguments name for cli or api context
|
||||
names = format_arg_names(str(argument_name),
|
||||
argument_options.pop('full', None))
|
||||
|
||||
if "type" in argument_options:
|
||||
argument_options['type'] = eval(argument_options['type'])
|
||||
|
||||
if "extra" in argument_options:
|
||||
extra = argument_options.pop('extra')
|
||||
argument_dest = self.add_argument(*names, **argument_options).dest
|
||||
extraparser.add_argument(self.get_default("_tid"),
|
||||
argument_dest, extra, validate_extra)
|
||||
continue
|
||||
|
||||
self.add_argument(*names, **argument_options)
|
||||
|
||||
def _get_nargs_pattern(self, action):
|
||||
if action.nargs == argparse.PARSER and not action.required:
|
||||
return '([-AO]*)'
|
||||
|
|
|
@ -80,6 +80,24 @@ class _HTTPArgumentParser(object):
|
|||
def get_default(self, dest):
|
||||
return self._parser.get_default(dest)
|
||||
|
||||
def add_arguments(self, arguments, extraparser, format_arg_names=None, validate_extra=True):
|
||||
for argument_name, argument_options in arguments.items():
|
||||
# will adapt arguments name for cli or api context
|
||||
names = format_arg_names(str(argument_name),
|
||||
argument_options.pop('full', None))
|
||||
|
||||
if "type" in argument_options:
|
||||
argument_options['type'] = eval(argument_options['type'])
|
||||
|
||||
if "extra" in argument_options:
|
||||
extra = argument_options.pop('extra')
|
||||
argument_dest = self.add_argument(*names, **argument_options).dest
|
||||
extraparser.add_argument(self.get_default("_tid"),
|
||||
argument_dest, extra, validate_extra)
|
||||
continue
|
||||
|
||||
self.add_argument(*names, **argument_options)
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
action = self._parser.add_argument(*args, **kwargs)
|
||||
|
||||
|
@ -387,6 +405,15 @@ class _ActionsMapPlugin(object):
|
|||
ret = self.actionsmap.process(arguments, timeout=30, route=_route)
|
||||
except MoulinetteError as e:
|
||||
raise error_to_response(e)
|
||||
except Exception as e:
|
||||
if isinstance(e, HTTPResponse):
|
||||
raise e
|
||||
import traceback
|
||||
tb = traceback.format_exc()
|
||||
logs = { "route": _route,
|
||||
"arguments": arguments,
|
||||
"traceback": tb }
|
||||
return HTTPErrorResponse(json_encode(logs))
|
||||
else:
|
||||
return format_for_response(ret)
|
||||
finally:
|
||||
|
@ -581,7 +608,7 @@ class ActionsMapParser(BaseActionsMapParser):
|
|||
if len(keys) == 0:
|
||||
raise ValueError("no valid api route found")
|
||||
else:
|
||||
raise AttributeError("no api route for action '%s'" % name)
|
||||
return None
|
||||
|
||||
# Create and append parser
|
||||
parser = _HTTPArgumentParser()
|
||||
|
|
|
@ -308,6 +308,15 @@ class ActionsMapParser(BaseActionsMapParser):
|
|||
deprecated=deprecated,
|
||||
deprecated_alias=deprecated_alias)
|
||||
|
||||
def add_global_arguments(self, arguments):
|
||||
for argument_name, argument_options in arguments.items():
|
||||
# will adapt arguments name for cli or api context
|
||||
names = self.format_arg_names(str(argument_name),
|
||||
argument_options.pop('full', None))
|
||||
|
||||
self.global_parser.add_argument(*names, **argument_options)
|
||||
|
||||
|
||||
def parse_args(self, args, **kwargs):
|
||||
try:
|
||||
ret = self._parser.parse_args(args)
|
||||
|
|
|
@ -9,9 +9,13 @@ sys.path.append("..")
|
|||
|
||||
|
||||
old_init = moulinette.core.Moulinette18n.__init__
|
||||
|
||||
|
||||
def monkey_path_i18n_init(self, package, default_locale="en"):
|
||||
old_init(self, package, default_locale)
|
||||
self.load_namespace("moulinette")
|
||||
|
||||
|
||||
moulinette.core.Moulinette18n.__init__ = monkey_path_i18n_init
|
||||
|
||||
|
||||
|
@ -21,16 +25,23 @@ moulinette.core.Moulinette18n.__init__ = monkey_path_i18n_init
|
|||
|
||||
|
||||
old_translate = moulinette.core.Translator.translate
|
||||
|
||||
|
||||
def new_translate(self, key, *args, **kwargs):
|
||||
|
||||
if key not in self._translations[self.default_locale].keys():
|
||||
raise KeyError("Unable to retrieve key %s for default locale !" % key)
|
||||
|
||||
return old_translate(self, key, *args, **kwargs)
|
||||
|
||||
|
||||
moulinette.core.Translator.translate = new_translate
|
||||
|
||||
|
||||
def new_m18nn(self, key, *args, **kwargs):
|
||||
return self._global.translate(key, *args, **kwargs)
|
||||
|
||||
|
||||
moulinette.core.Moulinette18n.g = new_m18nn
|
||||
|
||||
|
||||
|
@ -93,4 +104,3 @@ def pytest_cmdline_main(config):
|
|||
|
||||
# Initialize moulinette
|
||||
moulinette.init(logging_config=logging, _from_source=False)
|
||||
|
||||
|
|
|
@ -3,14 +3,12 @@
|
|||
import os
|
||||
import pwd
|
||||
import pytest
|
||||
import requests
|
||||
import requests_mock
|
||||
|
||||
# Moulinette specific
|
||||
from moulinette.core import MoulinetteError
|
||||
from moulinette.utils.filesystem import (
|
||||
read_file, read_json,
|
||||
write_to_file, append_to_file, write_to_json,
|
||||
from moulinette.utils.filesystem import (read_file, read_json,
|
||||
write_to_file, append_to_file,
|
||||
write_to_json,
|
||||
rm,
|
||||
chmod, chown)
|
||||
|
||||
|
@ -61,7 +59,7 @@ def test_read_file():
|
|||
def test_read_file_badfile():
|
||||
|
||||
with pytest.raises(MoulinetteError):
|
||||
read_file(TMP_TEST_FILE+"nope")
|
||||
read_file(TMP_TEST_FILE + "nope")
|
||||
|
||||
|
||||
def test_read_file_badpermissions():
|
||||
|
@ -295,5 +293,3 @@ def test_setpermissions_badgroup():
|
|||
|
||||
with pytest.raises(MoulinetteError):
|
||||
set_permissions(TMP_TEST_FILE, NON_ROOT_USER, "foo", 0111)
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
# General python lib
|
||||
import os
|
||||
import pwd
|
||||
import pytest
|
||||
import requests
|
||||
import requests_mock
|
||||
|
@ -14,10 +12,12 @@ from moulinette.utils.network import download_text, download_json
|
|||
|
||||
TEST_URL = "https://some.test.url/yolo.txt"
|
||||
|
||||
|
||||
def setup_function(function):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def teardown_function(function):
|
||||
|
||||
pass
|
||||
|
@ -88,5 +88,3 @@ def test_download_json_badjson():
|
|||
|
||||
with pytest.raises(MoulinetteError):
|
||||
download_json(TEST_URL)
|
||||
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ def switch_to_non_root_user():
|
|||
# Test run shell commands #
|
||||
###############################################################################
|
||||
|
||||
|
||||
def test_run_shell_command_list():
|
||||
|
||||
commands = ["rm -f %s" % TMP_TEST_FILE]
|
||||
|
@ -63,4 +64,3 @@ def test_run_shell_command_badpermissions():
|
|||
switch_to_non_root_user()
|
||||
with pytest.raises(CalledProcessError):
|
||||
run_commands(commands)
|
||||
|
||||
|
|
Loading…
Reference in a new issue