Repository: audreyr/cookiecutter (python)

Issue:
Replay does not get correct user config
I think we need to persist the currently chosen config file so that subsequent calls of ``config.get_user_config`` yield the same values for the session.

Currently **cookiecutter/replay.py** always points to ``os.path.expanduser('~/.cookiecutter_replay')``:

```python
replay_dir = get_user_config()['replay_dir']
```

Pull request:
Pass user config to replay
Change the signature of both ``replay.load`` and ``replay.dump`` to require a replay directory opposed to retrieving it from ``config.get_user_config()``.

Resolve #590 

Patch:
diff --git a/cookiecutter/main.py b/cookiecutter/main.py
index e6d858f..93b3c29 100755
--- a/cookiecutter/main.py
+++ b/cookiecutter/main.py
@@ -115,7 +115,7 @@ def cookiecutter(
     template_name = os.path.basename(template)
 
     if replay:
-        context = load(template_name)
+        context = load(config_dict['replay_dir'], template_name)
     else:
         context_file = os.path.join(repo_dir, 'cookiecutter.json')
         logging.debug('context_file is {0}'.format(context_file))
@@ -130,7 +130,7 @@ def cookiecutter(
         # except when 'no-input' flag is set
         context['cookiecutter'] = prompt_for_config(context, no_input)
 
-        dump(template_name, context)
+        dump(config_dict['replay_dir'], template_name, context)
 
     # Create project from local context and project template.
     return generate_files(
diff --git a/cookiecutter/replay.py b/cookiecutter/replay.py
index 627170d..bee7ec3 100644
--- a/cookiecutter/replay.py
+++ b/cookiecutter/replay.py
@@ -11,7 +11,6 @@ import json
 import os
 from past.builtins import basestring
 
-from .config import get_user_config
 from .utils import make_sure_path_exists
 
 
@@ -20,7 +19,10 @@ def get_file_name(replay_dir, template_name):
     return os.path.join(replay_dir, file_name)
 
 
-def dump(template_name, context):
+def dump(replay_dir, template_name, context):
+    if not make_sure_path_exists(replay_dir):
+        raise IOError('Unable to create replay dir at {}'.format(replay_dir))
+
     if not isinstance(template_name, basestring):
         raise TypeError('Template name is required to be of type str')
 
@@ -30,22 +32,16 @@ def dump(template_name, context):
     if 'cookiecutter' not in context:
         raise ValueError('Context is required to contain a cookiecutter key')
 
-    replay_dir = get_user_config()['replay_dir']
-
-    if not make_sure_path_exists(replay_dir):
-        raise IOError('Unable to create replay dir at {}'.format(replay_dir))
-
     replay_file = get_file_name(replay_dir, template_name)
 
     with open(replay_file, 'w') as outfile:
         json.dump(context, outfile)
 
 
-def load(template_name):
+def load(replay_dir, template_name):
     if not isinstance(template_name, basestring):
         raise TypeError('Template name is required to be of type str')
 
-    replay_dir = get_user_config()['replay_dir']
     replay_file = get_file_name(replay_dir, template_name)
 
     with open(replay_file, 'r') as infile:


Test patch:
diff --git a/tests/replay/conftest.py b/tests/replay/conftest.py
index 296f63a..adb7b64 100644
--- a/tests/replay/conftest.py
+++ b/tests/replay/conftest.py
@@ -1,7 +1,5 @@
 import pytest
 
-from cookiecutter import config
-
 
 @pytest.fixture
 def context():
@@ -22,10 +20,5 @@ def replay_test_dir():
 
 
 @pytest.fixture
-def mock_user_config(mocker, replay_test_dir):
-    user_config = config.DEFAULT_CONFIG
-    user_config.update({'replay_dir': replay_test_dir})
-
-    return mocker.patch(
-        'cookiecutter.replay.get_user_config', return_value=user_config
-    )
+def mock_user_config(mocker):
+    return mocker.patch('cookiecutter.main.get_user_config')
diff --git a/tests/replay/test_dump.py b/tests/replay/test_dump.py
index 0a0d067..d0715e6 100644
--- a/tests/replay/test_dump.py
+++ b/tests/replay/test_dump.py
@@ -34,24 +34,24 @@ def remove_replay_dump(request, replay_file):
     request.addfinalizer(fin_remove_replay_file)
 
 
-def test_type_error_if_no_template_name(context):
+def test_type_error_if_no_template_name(replay_test_dir, context):
     """Test that replay.dump raises if the tempate_name is not a valid str."""
     with pytest.raises(TypeError):
-        replay.dump(None, context)
+        replay.dump(replay_test_dir, None, context)
 
 
-def test_type_error_if_not_dict_context(template_name):
+def test_type_error_if_not_dict_context(replay_test_dir, template_name):
     """Test that replay.dump raises if the context is not of type dict."""
     with pytest.raises(TypeError):
-        replay.dump(template_name, 'not_a_dict')
+        replay.dump(replay_test_dir, template_name, 'not_a_dict')
 
 
-def test_value_error_if_key_missing_in_context(template_name):
+def test_value_error_if_key_missing_in_context(replay_test_dir, template_name):
     """Test that replay.dump raises if the context does not contain a key
     named 'cookiecutter'.
     """
     with pytest.raises(ValueError):
-        replay.dump(template_name, {'foo': 'bar'})
+        replay.dump(replay_test_dir, template_name, {'foo': 'bar'})
 
 
 @pytest.fixture
@@ -71,11 +71,14 @@ def mock_ensure_success(mocker):
 
 
 def test_ioerror_if_replay_dir_creation_fails(
-        mock_ensure_failure, mock_user_config, replay_test_dir):
+        mock_ensure_failure, replay_test_dir):
     """Test that replay.dump raises when the replay_dir cannot be created."""
 
     with pytest.raises(IOError):
-        replay.dump('foo', {'cookiecutter': {'hello': 'world'}})
+        replay.dump(
+            replay_test_dir,
+            'foo', {'cookiecutter': {'hello': 'world'}}
+        )
 
     mock_ensure_failure.assert_called_once_with(replay_test_dir)
 
@@ -89,9 +92,9 @@ def test_run_json_dump(mocker, mock_ensure_success, mock_user_config,
 
     mock_json_dump = mocker.patch('json.dump', side_effect=json.dump)
 
-    replay.dump(template_name, context)
+    replay.dump(replay_test_dir, template_name, context)
 
-    assert mock_user_config.call_count == 1
+    assert not mock_user_config.called
     mock_ensure_success.assert_called_once_with(replay_test_dir)
     spy_get_replay_file.assert_called_once_with(replay_test_dir, template_name)
 
diff --git a/tests/replay/test_load.py b/tests/replay/test_load.py
index 5876096..e02480c 100644
--- a/tests/replay/test_load.py
+++ b/tests/replay/test_load.py
@@ -25,24 +25,24 @@ def replay_file(replay_test_dir, template_name):
     return os.path.join(replay_test_dir, file_name)
 
 
-def test_type_error_if_no_template_name():
+def test_type_error_if_no_template_name(replay_test_dir):
     """Test that replay.load raises if the tempate_name is not a valid str."""
     with pytest.raises(TypeError):
-        replay.load(None)
+        replay.load(replay_test_dir, None)
 
 
-def test_value_error_if_key_missing_in_context(mocker):
+def test_value_error_if_key_missing_in_context(mocker, replay_test_dir):
     """Test that replay.load raises if the loaded context does not contain
     'cookiecutter'.
     """
     with pytest.raises(ValueError):
-        replay.load('invalid_replay')
+        replay.load(replay_test_dir, 'invalid_replay')
 
 
-def test_io_error_if_no_replay_file(mocker, mock_user_config):
+def test_io_error_if_no_replay_file(mocker, replay_test_dir):
     """Test that replay.load raises if it cannot find a replay file."""
     with pytest.raises(IOError):
-        replay.load('no_replay')
+        replay.load(replay_test_dir, 'no_replay')
 
 
 def test_run_json_load(mocker, mock_user_config, template_name,
@@ -54,9 +54,9 @@ def test_run_json_load(mocker, mock_user_config, template_name,
 
     mock_json_load = mocker.patch('json.load', side_effect=json.load)
 
-    loaded_context = replay.load(template_name)
+    loaded_context = replay.load(replay_test_dir, template_name)
 
-    assert mock_user_config.call_count == 1
+    assert not mock_user_config.called
     spy_get_replay_file.assert_called_once_with(replay_test_dir, template_name)
 
     assert mock_json_load.call_count == 1