<commit_before># -*- coding: utf-8 -*-

import threading

from . import expand_path
from .compat import urlparse
from .. import log
from ..doubleclick import click, ctx

logger = log.get(__name__)
password_key_prefix = 'vdirsyncer:'

try:
    import keyring
except ImportError:
    keyring = None


def get_password(username, resource, _lock=threading.Lock()):
    """tries to access saved password or asks user for it

    will try the following in this order:
        1. read password from netrc (and only the password, username
           in netrc will be ignored)
        2. read password from keyring (keyring needs to be installed)
        3. read password from the command passed as password_command in the
           general config section with username and host as parameters
        4a ask user for the password
         b save in keyring if installed and user agrees

    :param username: user's name on the server
    :type username: str/unicode
    :param resource: a resource to which the user has access via password,
                     it will be shortened to just the hostname. It is assumed
                     that each unique username/hostname combination only ever
                     uses the same password.
    :type resource: str/unicode
    :return: password
    :rtype: str/unicode


    """
    if ctx:
        password_cache = ctx.obj.setdefault('passwords', {})

    with _lock:
        host = urlparse.urlsplit(resource).hostname
        for func in (_password_from_command, _password_from_cache,
                     _password_from_netrc, _password_from_keyring):
            password = func(username, host)
            if password is not None:
                logger.debug('Got password for {} from {}'
                             .format(username, func.__doc__))
                return password

        prompt = ('Server password for {} at host {}'.format(username, host))
        password = click.prompt(prompt, hide_input=True)

        if ctx and func is not _password_from_cache:
            password_cache[(username, host)] = password
            if keyring is not None and \
               click.confirm('Save this password in the keyring?',
                             default=False):
                keyring.set_password(password_key_prefix + host,
                                     username, password)

        return password


def _password_from_cache(username, host):<commit_msg>Bugfix: Cache should be checked *before* command is called<commit_after># -*- coding: utf-8 -*-

import threading

from . import expand_path
from .compat import urlparse
from .. import log
from ..doubleclick import click, ctx

logger = log.get(__name__)
password_key_prefix = 'vdirsyncer:'

try:
    import keyring
except ImportError:
    keyring = None


def get_password(username, resource, _lock=threading.Lock()):
    """tries to access saved password or asks user for it

    will try the following in this order:
        1. read password from netrc (and only the password, username
           in netrc will be ignored)
        2. read password from keyring (keyring needs to be installed)
        3. read password from the command passed as password_command in the
           general config section with username and host as parameters
        4a ask user for the password
         b save in keyring if installed and user agrees

    :param username: user's name on the server
    :type username: str/unicode
    :param resource: a resource to which the user has access via password,
                     it will be shortened to just the hostname. It is assumed
                     that each unique username/hostname combination only ever
                     uses the same password.
    :type resource: str/unicode
    :return: password
    :rtype: str/unicode


    """
    if ctx:
        password_cache = ctx.obj.setdefault('passwords', {})

    with _lock:
        host = urlparse.urlsplit(resource).hostname
        for func in (_password_from_cache, _password_from_command,
                     _password_from_netrc, _password_from_keyring):
            password = func(username, host)
            if password is not None:
                logger.debug('Got password for {} from {}'
                             .format(username, func.__doc__))
                return password

        prompt = ('Server password for {} at host {}'.format(username, host))
        password = click.prompt(prompt, hide_input=True)

        if ctx and func is not _password_from_cache:
            password_cache[(username, host)] = password
            if keyring is not None and \
               click.confirm('Save this password in the keyring?',
                             default=False):
                keyring.set_password(password_key_prefix + host,
                                     username, password)

        return password


def _password_from_cache(username, host):
{'fraction_non_alphanumeric': 0.06655811113372685, 'fraction_numerical': 0.0020354162426216163, 'mean_word_length': 2.184705119896306, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3282544', 'n_tokens_mistral': 1240, 'n_tokens_neox': 1194, 'n_words': 481}