Merge pull request #269 from YunoHost/fix-argparse

Fix argparse
This commit is contained in:
Alexandre Aubin 2021-01-31 14:41:11 +01:00 committed by GitHub
commit cf98095303
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 4 deletions

View file

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

View file

@ -21,6 +21,37 @@ from moulinette.interfaces import (
)
from moulinette.utils import log
# 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
logger = log.getLogger("moulinette.cli")

View file

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

View file

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