Fix bug in keyring fetching code

Leading to infinite loop when the password is simply not there.

Also fixed some import styling again
This commit is contained in:
Markus Unterwaditzer 2014-06-19 18:06:34 +02:00
parent 289ac2cfac
commit 2fb58d6bcd
5 changed files with 50 additions and 7 deletions

View file

@ -15,6 +15,10 @@ from vdirsyncer.utils.vobject import normalize_item as _normalize_item
vdirsyncer.log.set_level(vdirsyncer.log.logging.DEBUG) vdirsyncer.log.set_level(vdirsyncer.log.logging.DEBUG)
def blow_up(*a, **kw):
raise AssertionError('Did not expect to be called.')
def normalize_item(item): def normalize_item(item):
if not isinstance(item, text_type): if not isinstance(item, text_type):
item = item.raw item = item.raw

View file

@ -7,11 +7,13 @@
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
''' '''
import click
from click.testing import CliRunner
import pytest import pytest
import vdirsyncer.utils as utils import vdirsyncer.utils as utils
from vdirsyncer.utils.vobject import split_collection from vdirsyncer.utils.vobject import split_collection
from .. import normalize_item, SIMPLE_TEMPLATE, BARE_EVENT_TEMPLATE from .. import blow_up, normalize_item, SIMPLE_TEMPLATE, BARE_EVENT_TEMPLATE
def test_parse_options(): def test_parse_options():
@ -58,7 +60,7 @@ def test_get_password_from_netrc(monkeypatch):
return username, 'bogus', password return username, 'bogus', password
monkeypatch.setattr('netrc.netrc', Netrc) monkeypatch.setattr('netrc.netrc', Netrc)
monkeypatch.setattr('getpass.getpass', None) monkeypatch.setattr('getpass.getpass', blow_up)
_password = utils.get_password(username, resource) _password = utils.get_password(username, resource)
assert _password == password assert _password == password
@ -101,13 +103,46 @@ def test_get_password_from_system_keyring(monkeypatch, resources_to_test):
return None return None
monkeypatch.setattr('netrc.netrc', Netrc) monkeypatch.setattr('netrc.netrc', Netrc)
monkeypatch.setattr('getpass.getpass', None) monkeypatch.setattr('getpass.getpass', blow_up)
_password = utils.get_password(username, resource) _password = utils.get_password(username, resource)
assert _password == password assert _password == password
assert netrc_calls == [hostname] assert netrc_calls == [hostname]
def test_get_password_from_prompt(monkeypatch):
getpass_calls = []
class Netrc(object):
def authenticators(self, hostname):
return None
class Keyring(object):
def get_password(self, *a, **kw):
return None
monkeypatch.setattr('netrc.netrc', Netrc)
monkeypatch.setattr(utils, 'keyring', Keyring())
user = 'my_user'
resource = 'http://example.com'
@click.command()
def fake_app():
x = utils.get_password(user, resource)
click.echo('Password is {}'.format(x))
runner = CliRunner()
result = runner.invoke(fake_app, input='my_password\n\n')
assert not result.exception
assert result.output.splitlines() == [
'Server password for {} at the resource {}: '.format(user, resource),
'Save this password in the keyring? [y/N]: ',
'Password is my_password'
]
def test_get_class_init_args(): def test_get_class_init_args():
class Foobar(object): class Foobar(object):
def __init__(self, foo, bar, baz=None): def __init__(self, foo, bar, baz=None):

View file

@ -7,10 +7,10 @@
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
''' '''
import functools
import json import json
import os import os
import sys import sys
import functools
import click import click

View file

@ -7,6 +7,7 @@
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
''' '''
import logging import logging
import click import click

View file

@ -9,9 +9,10 @@
import os import os
import requests
import click import click
import requests
from .. import exceptions, log from .. import exceptions, log
from .compat import iteritems, urlparse from .compat import iteritems, urlparse
@ -117,7 +118,9 @@ def _password_from_keyring(username, resource):
parsed = urlparse.urlsplit(key) parsed = urlparse.urlsplit(key)
path = parsed.path path = parsed.path
if path.endswith('/'): if not path:
return None
elif path.endswith('/'):
path = path.rstrip('/') path = path.rstrip('/')
else: else:
path = path.rsplit('/', 1)[0] + '/' path = path.rsplit('/', 1)[0] + '/'
@ -165,7 +168,7 @@ def get_password(username, resource):
prompt = ('Server password for {} at the resource {}' prompt = ('Server password for {} at the resource {}'
.format(username, resource)) .format(username, resource))
password = click.prompt(prompt=prompt, hide_input=True) password = click.prompt(prompt, hide_input=True)
if keyring is not None and \ if keyring is not None and \
click.confirm('Save this password in the keyring?', default=False): click.confirm('Save this password in the keyring?', default=False):