From 9077569c221c271982cacba40cba7bcf60deed98 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Tue, 26 Jan 2021 12:05:05 +0100 Subject: [PATCH 1/4] in python3 OrderedDict and array are not the same --- moulinette/interfaces/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moulinette/interfaces/__init__.py b/moulinette/interfaces/__init__.py index 624ab7fd..a73bc5f6 100644 --- a/moulinette/interfaces/__init__.py +++ b/moulinette/interfaces/__init__.py @@ -584,12 +584,12 @@ class ExtendedArgumentParser(argparse.ArgumentParser): ] # Display each section (actions and subcategories) - if actions_choices != []: + if actions_choices: formatter.start_section("actions") formatter.add_arguments([actions_subparser]) formatter.end_section() - if subcategories_choices != []: + if subcategories_choices: formatter.start_section("subcategories") formatter.add_arguments([subcategories_subparser]) formatter.end_section() From 84d250c1c2e88e9e826b94043cc71c8585ad5224 Mon Sep 17 00:00:00 2001 From: Kay0u Date: Tue, 26 Jan 2021 12:05:25 +0100 Subject: [PATCH 2/4] monkey patch _get_action_name --- moulinette/interfaces/cli.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/moulinette/interfaces/cli.py b/moulinette/interfaces/cli.py index 11d219b1..9433b116 100644 --- a/moulinette/interfaces/cli.py +++ b/moulinette/interfaces/cli.py @@ -6,6 +6,39 @@ import getpass import locale import logging from argparse import SUPPRESS + +# Monkeypatch _get_action_name function because there is an annoying bug +# Explained here: https://bugs.python.org/issue29298 +# Fixed by: https://github.com/python/cpython/pull/3680 +# To reproduce the bug, just launch a command line without action +# For example: +# yunohost firewall +# It should display: +# usage: yunohost firewall {list,reload,allow,disallow,upnp,stop} ... [-h] +# yunohost firewall: error: the following arguments are required: {list,reload,allow,disallow,upnp,stop} +# But it display instead: +# Error: unable to parse arguments 'firewall' because: sequence item 0: expected str instance, NoneType found + +import argparse + + +def monkey_get_action_name(argument): + if argument is None: + return None + elif argument.option_strings: + return "/".join(argument.option_strings) + elif argument.metavar not in (None, SUPPRESS): + return argument.metavar + elif argument.dest not in (None, SUPPRESS): + return argument.dest + elif argument.choices: + return "{" + ",".join(argument.choices) + "}" + else: + return None + + +argparse._get_action_name = monkey_get_action_name + from collections import OrderedDict from datetime import date, datetime From 53cbca2c1ec1dce4203e63004fefaa70dae278df Mon Sep 17 00:00:00 2001 From: Kay0u Date: Tue, 26 Jan 2021 21:19:26 +0100 Subject: [PATCH 3/4] Add test without action --- moulinette/interfaces/cli.py | 30 ++++++++++++++---------------- test/test_auth.py | 12 ++++++++++++ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/moulinette/interfaces/cli.py b/moulinette/interfaces/cli.py index 9433b116..39b5f9a2 100644 --- a/moulinette/interfaces/cli.py +++ b/moulinette/interfaces/cli.py @@ -6,6 +6,20 @@ import getpass import locale import logging from argparse import SUPPRESS +from collections import OrderedDict +from datetime import date, datetime + +import argcomplete + +from moulinette import msignals, m18n +from moulinette.actionsmap import ActionsMap +from moulinette.core import MoulinetteError +from moulinette.interfaces import ( + BaseActionsMapParser, + BaseInterface, + ExtendedArgumentParser, +) +from moulinette.utils import log # Monkeypatch _get_action_name function because there is an annoying bug # Explained here: https://bugs.python.org/issue29298 @@ -39,22 +53,6 @@ def monkey_get_action_name(argument): argparse._get_action_name = monkey_get_action_name -from collections import OrderedDict -from datetime import date, datetime - -import argcomplete - -from moulinette import msignals, m18n -from moulinette.actionsmap import ActionsMap -from moulinette.core import MoulinetteError -from moulinette.interfaces import ( - BaseActionsMapParser, - BaseInterface, - ExtendedArgumentParser, -) -from moulinette.utils import log - - logger = log.getLogger("moulinette.cli") diff --git a/test/test_auth.py b/test/test_auth.py index 624ebccd..b3237089 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -207,6 +207,10 @@ class TestAuthAPI: mocker.patch("moulinette.Moulinette18n.g", return_value=error) moulinette_webapi.get("/test-auth/with_type_int/yoloswag", status=400) + def test_request_arg_without_action(self, moulinette_webapi, caplog, mocker): + self.login(moulinette_webapi) + moulinette_webapi.get("/test-auth", status=404) + class TestAuthCLI: def test_login(self, moulinette_cli, capsys, mocker): @@ -336,3 +340,11 @@ class TestAuthCLI: message = capsys.readouterr() assert "invalid int value" in message.err + + def test_request_arg_without_action(self, moulinette_cli, capsys, mocker): + with pytest.raises(SystemExit): + moulinette_cli.run(["testauth"], output_as="plain") + + message = capsys.readouterr() + + assert "error: the following arguments are required:" in message.err From 5cd0cb752b61e277ac46a86ca77973b0f0b0f25c Mon Sep 17 00:00:00 2001 From: Kay0u Date: Tue, 26 Jan 2021 21:38:09 +0100 Subject: [PATCH 4/4] Remove copy pasta --- test/conftest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 2f903d8e..8762d57d 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -132,8 +132,6 @@ def moulinette_webapi(moulinette): @pytest.fixture def moulinette_cli(moulinette, mocker): - # Dirty hack needed, otherwise cookies ain't reused between request .. not - # sure why :| import argparse parser = argparse.ArgumentParser(add_help=False)