Source code for cookiecutter.prompt

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
cookiecutter.prompt
---------------------

Functions for prompting the user for project info.
"""

from collections import OrderedDict

import click
from past.builtins import basestring

from future.utils import iteritems

from jinja2.exceptions import UndefinedError

from .exceptions import UndefinedVariableInTemplate
from .environment import StrictEnvironment


[docs]def read_user_variable(var_name, default_value): """Prompt the user for the given variable and return the entered value or the given default. :param str var_name: Variable of the context to query the user :param default_value: Value that will be returned if no input happens """ # Please see http://click.pocoo.org/4/api/#click.prompt return click.prompt(var_name, default=default_value)
[docs]def read_user_yes_no(question, default_value): """Prompt the user to reply with 'yes' or 'no' (or equivalent values). Note: Possible choices are 'true', '1', 'yes', 'y' or 'false', '0', 'no', 'n' :param str question: Question to the user :param default_value: Value that will be returned if no input happens """ # Please see http://click.pocoo.org/4/api/#click.prompt return click.prompt( question, default=default_value, type=click.BOOL )
[docs]def read_user_choice(var_name, options): """Prompt the user to choose from several options for the given variable. The first item will be returned if no input happens. :param str var_name: Variable as specified in the context :param list options: Sequence of options that are available to select from :return: Exactly one item of ``options`` that has been chosen by the user """ # Please see http://click.pocoo.org/4/api/#click.prompt if not isinstance(options, list): raise TypeError if not options: raise ValueError choice_map = OrderedDict( (u'{}'.format(i), value) for i, value in enumerate(options, 1) ) choices = choice_map.keys() default = u'1' choice_lines = [u'{} - {}'.format(*c) for c in choice_map.items()] prompt = u'\n'.join(( u'Select {}:'.format(var_name), u'\n'.join(choice_lines), u'Choose from {}'.format(u', '.join(choices)) )) user_choice = click.prompt( prompt, type=click.Choice(choices), default=default ) return choice_map[user_choice]
[docs]def render_variable(env, raw, cookiecutter_dict): if raw is None: return None if not isinstance(raw, basestring): raw = str(raw) template = env.from_string(raw) rendered_template = template.render(cookiecutter=cookiecutter_dict) return rendered_template
[docs]def prompt_choice_for_config(cookiecutter_dict, env, key, options, no_input): """Prompt the user which option to choose from the given. Each of the possible choices is rendered beforehand. """ rendered_options = [ render_variable(env, raw, cookiecutter_dict) for raw in options ] if no_input: return rendered_options[0] return read_user_choice(key, rendered_options)
[docs]def prompt_for_config(context, no_input=False): """ Prompts the user to enter new config, using context as a source for the field names and sample values. :param no_input: Prompt the user at command line for manual configuration? """ cookiecutter_dict = {} env = StrictEnvironment(context=context) for key, raw in iteritems(context[u'cookiecutter']): if key.startswith(u'_'): cookiecutter_dict[key] = raw continue try: if isinstance(raw, list): # We are dealing with a choice variable val = prompt_choice_for_config( cookiecutter_dict, env, key, raw, no_input ) else: # We are dealing with a regular variable val = render_variable(env, raw, cookiecutter_dict) if not no_input: val = read_user_variable(key, val) except UndefinedError as err: msg = "Unable to render variable '{}'".format(key) raise UndefinedVariableInTemplate(msg, err, context) cookiecutter_dict[key] = val return cookiecutter_dict