Repository: audreyr/cookiecutter
Pull request #451 (2015-05-05 22:49:34)

Use click for prompting in read_response
This PR removes ``read_response`` from ``compat.py`` in favor of a re-implementation using [click.prompt](http://click.pocoo.org/4/api/#click.prompt).

I wrote a simple test to make sure that ``click.prompt`` is being called with the correct arguments so that it mimics the current prompting scheme by leaving the actual prompt generation to ``prompt_for_config``.

I will submit another request to change ``query_yes_no`` and to introduce the choices feature of #441 (and close #443). 

Please let me know your thoughts. :smile: 


Patch:
diff --git a/cookiecutter/compat.py b/cookiecutter/compat.py
index 7cd280f..e910da1 100644
--- a/cookiecutter/compat.py
+++ b/cookiecutter/compat.py
@@ -4,23 +4,13 @@ import sys
 PY3 = sys.version_info[0] == 3
 OLD_PY2 = sys.version_info[:2] < (2, 7)
 
+
 if PY3:  # pragma: no cover
     input_str = 'builtins.input'
     iteritems = lambda d: iter(d.items())
     from unittest.mock import patch
     from io import StringIO
 
-    def read_response(prompt=''):
-        """
-        Prompt the user for a response.
-
-        Prints the given prompt (which should be a Unicode string),
-        and returns the text entered by the user as a Unicode string.
-
-        :param prompt: A Unicode string that is presented to the user.
-        """
-        # The Python 3 input function does exactly what we want
-        return input(prompt)
 
 else:  # pragma: no cover
     from __builtin__ import raw_input
@@ -30,32 +20,6 @@ else:  # pragma: no cover
     from mock import patch
     from cStringIO import StringIO
 
-    def read_response(prompt=''):
-        """
-        Prompt the user for a response.
-
-        Prints the given prompt (which should be a Unicode string),
-        and returns the text entered by the user as a Unicode string.
-
-        :param prompt: A Unicode string that is presented to the user.
-        """
-        # For Python 2, raw_input takes a byte string argument for the prompt.
-        # This must be encoded using the encoding used by sys.stdout.
-        # The result is a byte string encoding using sys.stdin.encoding.
-        # However, if the program is not being run interactively, sys.stdout
-        # and sys.stdin may not have encoding attributes.
-        # In that case we don't print a prompt (stdin/out isn't interactive,
-        # so prompting is pointless), and we assume the returned data is
-        # encoded using sys.getdefaultencoding(). This may not be right,
-        # but it's likely the best we can do.
-        # Isn't Python 2 encoding support wonderful? :-)
-        if sys.stdout.encoding:
-            prompt = prompt.encode(sys.stdout.encoding)
-        else:
-            prompt = ''
-        enc = sys.stdin.encoding or sys.getdefaultencoding()
-        return raw_input(prompt).decode(enc)
-
 
 if PY3:  # Forced testing
 
diff --git a/cookiecutter/prompt.py b/cookiecutter/prompt.py
index 5e8bd67..12b96e2 100755
--- a/cookiecutter/prompt.py
+++ b/cookiecutter/prompt.py
@@ -11,10 +11,29 @@ Functions for prompting the user for project info.
 from __future__ import unicode_literals
 import sys
 
-from .compat import iteritems, read_response, is_string
+import click
+
+from .compat import iteritems, is_string
 from jinja2.environment import Environment
 
 
+def read_response(prompt=''):
+    """Prompt the user and return the entered value or an empty string.
+
+    :param str prompt: Text to display to the user
+    """
+    # Please see http://click.pocoo.org/4/api/#click.prompt
+    # default: use an empty string if no input happens
+    # prompt_suffix: do not add a suffix to the prompt
+    # show_default: the prompt is expected to mention the default itself
+    return click.prompt(
+        prompt,
+        default='',
+        prompt_suffix='',
+        show_default=False,
+    )
+
+
 def prompt_for_config(context, no_input=False):
     """
     Prompts the user to enter new config, using context as a source for the


Test patch:
diff --git a/tests/test_read_response.py b/tests/test_read_response.py
new file mode 100755
index 0000000..e243556
--- /dev/null
+++ b/tests/test_read_response.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+test_read_response
+------------------
+"""
+
+from __future__ import unicode_literals
+
+from cookiecutter.prompt import read_response
+
+PROMPT = 'project_name (default is "Kivy Project")?'
+
+
+def _monkey_prompt(prompt, **kwargs):
+    expected_kwargs = {
+        'default': '',
+        'prompt_suffix': '',
+        'show_default': False
+    }
+    assert prompt == PROMPT
+    assert kwargs == expected_kwargs
+    return 'Hello World'
+
+
+def test_click_invocation(capsys, monkeypatch):
+    monkeypatch.setattr('click.prompt', _monkey_prompt)
+    assert read_response(PROMPT) == 'Hello World'