From 768f27018fa1a8e1fe1a22c100eba2610eff69a0 Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Thu, 23 May 2019 10:29:09 +0200 Subject: [PATCH] Fix #4: lazy password evaluation --- funkwhale_cli/cli.py | 31 ++++++++++++++++++++++++++++++- tests/test_cli.py | 18 ++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/funkwhale_cli/cli.py b/funkwhale_cli/cli.py index 12bc25f..fa892e3 100644 --- a/funkwhale_cli/cli.py +++ b/funkwhale_cli/cli.py @@ -88,6 +88,35 @@ RAW_DECORATOR = click.option( "--raw", is_flag=True, help="Directly output JSON returned by the happy" ) +class lazy_credential(): + """ + A proxy object to request access to the proxy object at the later possible point, + cf #4 + """ + def __init__(self, *args): + self.args = args + self._cached_value = None + + @property + def value(self): + if self._cached_value: + return self._cached_value + v = keyring.get_password(*self.args) + self._cached_value = v + return v + + def __str__(self): + return str(self.value) + + def __eq__(self, other): + return self.value == other + + def __repr__(self): + return str(self.value) + + def __bool__(self): + return bool(self.value) + def set_server(ctx, url, token): ctx.ensure_object(dict) @@ -96,7 +125,7 @@ def set_server(ctx, url, token): ctx.obj["SERVER_NETLOC"] = parsed.netloc ctx.obj["SERVER_PROTOCOL"] = parsed.scheme try: - token = token or keyring.get_password(url, "_") + token = token or lazy_credential(url, "_") except ValueError as e: raise click.ClickException("Error while retrieving password from keyring: {}. Your password may be incorrect.".format(e.args[0])) except Exception as e: diff --git a/tests/test_cli.py b/tests/test_cli.py index 4697133..5ba5983 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,5 +1,6 @@ import pytest import click +import keyring from funkwhale_cli import api from funkwhale_cli import cli @@ -61,3 +62,20 @@ def test_delete_command(group, cli_ctx, session, responses): ) def test_get_pagination_data(input, output): assert cli.get_pagination_data(input) == output + + +def test_lazy_credential(mocker): + get_password = mocker.patch("keyring.get_password", return_value="password") + credential = cli.lazy_credential("http://testurl", "_") + + get_password.assert_not_called() + + str(credential) + + get_password.assert_called_once_with("http://testurl", "_") + + assert credential == "password" + + # result is cached + str(credential) + assert get_password.call_count == 1 -- GitLab