### tests/test_get_config.py
"""Collection of tests around loading cookiecutter config."""

from pathlib import Path

import pytest
import yaml

from cookiecutter import config
from cookiecutter.exceptions import ConfigDoesNotExistException, InvalidConfiguration


def test_merge_configs():
    """Verify default and user config merged in expected way."""
    default = {
        'cookiecutters_dir': '/home/example/some-path-to-templates',
        'replay_dir': '/home/example/some-path-to-replay-files',
        'default_context': {},
        'abbreviations': {
            'gh': 'https://github.com/{0}.git',
            'gl': 'https://gitlab.com/{0}.git',
            'bb': 'https://bitbucket.org/{0}',
        },
    }

    user_config = {
        'default_context': {
            'full_name': 'Raphael Pierzina',
            'github_username': 'hackebrot',
        },
        'abbreviations': {
            'gl': 'https://gitlab.com/hackebrot/{0}.git',
            'pytest-plugin': 'https://github.com/pytest-dev/pytest-plugin.git',
        },
    }

    expected_config = {
        'cookiecutters_dir': '/home/example/some-path-to-templates',
        'replay_dir': '/home/example/some-path-to-replay-files',
        'default_context': {
            'full_name': 'Raphael Pierzina',
            'github_username': 'hackebrot',
        },
        'abbreviations': {
            'gh': 'https://github.com/{0}.git',
            'gl': 'https://gitlab.com/hackebrot/{0}.git',
            'bb': 'https://bitbucket.org/{0}',
            'pytest-plugin': 'https://github.com/pytest-dev/pytest-plugin.git',
        },
    }

    assert config.merge_configs(default, user_config) == expected_config


def test_get_config():
    """Verify valid config opened and rendered correctly."""
    conf = config.get_config('tests/test-config/valid-config.yaml')
    expected_conf = {
        'cookiecutters_dir': '/home/example/some-path-to-templates',
        'replay_dir': '/home/example/some-path-to-replay-files',
        'default_context': {
            'full_name': 'Firstname Lastname',
            'email': 'firstname.lastname@gmail.com',
            'github_username': 'example',
            'project': {
                'description': 'description',
                'tags': [
                    'first',
                    'second',
                    'third',
                ],
            },
        },
        'abbreviations': {
            'gh': 'https://github.com/{0}.git',
            'gl': 'https://gitlab.com/{0}.git',
            'bb': 'https://bitbucket.org/{0}',
            'helloworld': 'https://github.com/hackebrot/helloworld',
        },
    }
    assert conf == expected_conf


def test_get_config_does_not_exist():
    """Check that `exceptions.ConfigDoesNotExistException` is raised when \
    attempting to get a non-existent config file."""
    expected_error_msg = 'Config file tests/not-exist.yaml does not exist.'
    with pytest.raises(ConfigDoesNotExistException) as exc_info:
        config.get_config('tests/not-exist.yaml')
    assert str(exc_info.value) == expected_error_msg


def test_invalid_config():
    """An invalid config file should raise an `InvalidConfiguration` \
    exception."""
    expected_error_msg = (
        'Unable to parse YAML file tests/test-config/invalid-config.yaml.'
    )
    with pytest.raises(InvalidConfiguration) as exc_info:
        config.get_config('tests/test-config/invalid-config.yaml')
        assert expected_error_msg in str(exc_info.value)
        assert isinstance(exc_info.value.__cause__, yaml.YAMLError)


def test_get_config_with_defaults():
    """A config file that overrides 1 of 3 defaults."""
    conf = config.get_config('tests/test-config/valid-partial-config.yaml')
    default_cookiecutters_dir = Path('~/.cookiecutters').expanduser()
    default_replay_dir = Path('~/.cookiecutter_replay').expanduser()
    expected_conf = {
        'cookiecutters_dir': str(default_cookiecutters_dir),
        'replay_dir': str(default_replay_dir),
        'default_context': {
            'full_name': 'Firstname Lastname',
            'email': 'firstname.lastname@gmail.com',
            'github_username': 'example',
        },
        'abbreviations': {
            'gh': 'https://github.com/{0}.git',
            'gl': 'https://gitlab.com/{0}.git',
            'bb': 'https://bitbucket.org/{0}',
        },
    }
    assert conf == expected_conf


def test_get_config_empty_config_file():
    """An empty config file results in the default config."""
    conf = config.get_config('tests/test-config/empty-config.yaml')
    assert conf == config.DEFAULT_CONFIG


def test_get_config_invalid_file_with_array_as_top_level_element():
    """An exception should be raised if top-level element is array."""
    expected_error_msg = (
        'Top-level element of YAML file '
        'tests/test-config/invalid-config-w-array.yaml should be an object.'
    )
    with pytest.raises(InvalidConfiguration) as exc_info:
        config.get_config('tests/test-config/invalid-config-w-array.yaml')
    assert expected_error_msg in str(exc_info.value)


def test_get_config_invalid_file_with_multiple_docs():
    """An exception should be raised if config file contains multiple docs."""
    expected_error_msg = (
        'Unable to parse YAML file '
        'tests/test-config/invalid-config-w-multiple-docs.yaml.'
    )
    with pytest.raises(InvalidConfiguration) as exc_info:
        config.get_config('tests/test-config/invalid-config-w-multiple-docs.yaml')
    assert expected_error_msg in str(exc_info.value)
### tests/test_prompt.py
"""Tests for `cookiecutter.prompt` module."""

import json
import platform
import sys
from collections import OrderedDict
from pathlib import Path

import click
import pytest

from cookiecutter import environment, exceptions, prompt


@pytest.fixture(autouse=True)
def patch_readline_on_win(monkeypatch):
    """Fixture. Overwrite windows end of line to linux standard."""
    if 'windows' in platform.platform().lower():
        monkeypatch.setattr('sys.stdin.readline', lambda: '\n')


class TestRenderVariable:
    """Class to unite simple and complex tests for render_variable function."""

    @pytest.mark.parametrize(
        'raw_var, rendered_var',
        [
            (1, '1'),
            (True, True),
            ('foo', 'foo'),
            ('{{cookiecutter.project}}', 'foobar'),
            (None, None),
        ],
    )
    def test_convert_to_str(self, mocker, raw_var, rendered_var):
        """Verify simple items correctly rendered to strings."""
        env = environment.StrictEnvironment()
        from_string = mocker.patch(
            'cookiecutter.utils.StrictEnvironment.from_string', wraps=env.from_string
        )
        context = {'project': 'foobar'}

        result = prompt.render_variable(env, raw_var, context)
        assert result == rendered_var

        # Make sure that non None non str variables are converted beforehand
        if raw_var is not None and not isinstance(raw_var, bool):
            if not isinstance(raw_var, str):
                raw_var = str(raw_var)
            from_string.assert_called_once_with(raw_var)
        else:
            assert not from_string.called

    @pytest.mark.parametrize(
        'raw_var, rendered_var',
        [
            ({1: True, 'foo': False}, {'1': True, 'foo': False}),
            (
                {'{{cookiecutter.project}}': ['foo', 1], 'bar': False},
                {'foobar': ['foo', '1'], 'bar': False},
            ),
            (['foo', '{{cookiecutter.project}}', None], ['foo', 'foobar', None]),
        ],
    )
    def test_convert_to_str_complex_variables(self, raw_var, rendered_var):
        """Verify tree items correctly rendered."""
        env = environment.StrictEnvironment()
        context = {'project': 'foobar'}

        result = prompt.render_variable(env, raw_var, context)
        assert result == rendered_var


class TestPrompt:
    """Class to unite user prompt related tests."""

    @pytest.mark.parametrize(
        'context',
        [
            {'cookiecutter': {'full_name': 'Your Name'}},
            {'cookiecutter': {'full_name': 'Řekni či napiš své jméno'}},
        ],
        ids=['ASCII default prompt/input', 'Unicode default prompt/input'],
    )
    def test_prompt_for_config(self, monkeypatch, context):
        """Verify `prompt_for_config` call `read_user_variable` on text request."""
        monkeypatch.setattr(
            'cookiecutter.prompt.read_user_variable',
            lambda var, default, prompts, prefix: default,
        )

        cookiecutter_dict = prompt.prompt_for_config(context)
        assert cookiecutter_dict == context['cookiecutter']

    @pytest.mark.parametrize(
        'context',
        [
            {
                'cookiecutter': {
                    'full_name': 'Your Name',
                    'check': ['yes', 'no'],
                    'nothing': 'ok',
                    '__prompts__': {
                        'full_name': 'Name please',
                        'check': 'Checking',
                    },
                }
            },
        ],
        ids=['ASCII default prompt/input'],
    )
    def test_prompt_for_config_with_human_prompts(self, monkeypatch, context):
        """Verify call `read_user_variable` on request when human-readable prompts."""
        monkeypatch.setattr(
            'cookiecutter.prompt.read_user_variable',
            lambda var, default, prompts, prefix: default,
        )
        monkeypatch.setattr(
            'cookiecutter.prompt.read_user_yes_no',
            lambda var, default, prompts, prefix: default,
        )
        monkeypatch.setattr(
            'cookiecutter.prompt.read_user_choice',
            lambda var, default, prompts, prefix: default,
        )

        cookiecutter_dict = prompt.prompt_for_config(context)
        assert cookiecutter_dict == context['cookiecutter']

    @pytest.mark.parametrize(
        'context',
        [
            {
                'cookiecutter': {
                    'full_name': 'Your Name',
                    'check': ['yes', 'no'],
                    '__prompts__': {
                        'check': 'Checking',
                    },
                }
            },
            {
                'cookiecutter': {
                    'full_name': 'Your Name',
                    'check': ['yes', 'no'],
                    '__prompts__': {
                        'full_name': 'Name please',
                        'check': {'__prompt__': 'Checking', 'yes': 'Yes', 'no': 'No'},
                    },
                }
            },
            {
                'cookiecutter': {
                    'full_name': 'Your Name',
                    'check': ['yes', 'no'],
                    '__prompts__': {
                        'full_name': 'Name please',
                        'check': {'no': 'No'},
                    },
                }
            },
        ],
    )
    def test_prompt_for_config_with_human_choices(self, monkeypatch, context):
        """Test prompts when human-readable labels for user choices."""
        runner = click.testing.CliRunner()
        with runner.isolation(input="\n\n\n"):
            cookiecutter_dict = prompt.prompt_for_config(context)

        assert dict(cookiecutter_dict) == {'full_name': 'Your Name', 'check': 'yes'}

    def test_prompt_for_config_dict(self, monkeypatch):
        """Verify `prompt_for_config` call `read_user_variable` on dict request."""
        monkeypatch.setattr(
            'cookiecutter.prompt.read_user_dict',
            lambda var, default, prompts, prefix: {"key": "value", "integer": 37},
        )
        context = {'cookiecutter': {'details': {}}}

        cookiecutter_dict = prompt.prompt_for_config(context)
        assert cookiecutter_dict == {'details': {'key': 'value', 'integer': 37}}

    def test_should_render_dict(self):
        """Verify template inside dictionary variable rendered."""
        context = {
            'cookiecutter': {
                'project_name': 'Slartibartfast',
                'details': {
                    '{{cookiecutter.project_name}}': '{{cookiecutter.project_name}}'
                },
            }
        }

        cookiecutter_dict = prompt.prompt_for_config(context, no_input=True)
        assert cookiecutter_dict == {
            'project_name': 'Slartibartfast',
            'details': {'Slartibartfast': 'Slartibartfast'},
        }

    def test_should_render_deep_dict(self):
        """Verify nested structures like dict in dict, rendered correctly."""
        context = {
            'cookiecutter': {
                'project_name': "Slartibartfast",
                'details': {
                    "key": "value",
                    "integer_key": 37,
                    "other_name": '{{cookiecutter.project_name}}',
                    "dict_key": {
                        "deep_key": "deep_value",
                        "deep_integer": 42,
                        "deep_other_name": '{{cookiecutter.project_name}}',
                        "deep_list": [
                            "deep value 1",
                            "{{cookiecutter.project_name}}",
                            "deep value 3",
                        ],
                    },
                    "list_key": [
                        "value 1",
                        "{{cookiecutter.project_name}}",
                        "value 3",
                    ],
                },
            }
        }

        cookiecutter_dict = prompt.prompt_for_config(context, no_input=True)
        assert cookiecutter_dict == {
            'project_name': "Slartibartfast",
            'details': {
                "key": "value",
                "integer_key": "37",
                "other_name": "Slartibartfast",
                "dict_key": {
                    "deep_key": "deep_value",
                    "deep_integer": "42",
                    "deep_other_name": "Slartibartfast",
                    "deep_list": ["deep value 1", "Slartibartfast", "deep value 3"],
                },
                "list_key": ["value 1", "Slartibartfast", "value 3"],
            },
        }

    def test_should_render_deep_dict_with_human_prompts(self):
        """Verify dict rendered correctly when human-readable prompts."""
        context = {
            'cookiecutter': {
                'project_name': "Slartibartfast",
                'details': {
                    "key": "value",
                    "integer_key": 37,
                    "other_name": '{{cookiecutter.project_name}}',
                    "dict_key": {
                        "deep_key": "deep_value",
                    },
                },
                '__prompts__': {'project_name': 'Project name'},
            }
        }
### tests/test_read_user_variable.py
"""test_read_user_variable."""

impo<response clipped><NOTE>Due to the max output limit, only part of the full response has been shown to you.</NOTE>=True, output_dir=str(tmp_path)
    )
    changelog_file = os.path.join(project_dir, 'id')
    assert os.path.isfile(changelog_file)

    with Path(changelog_file).open(encoding='utf-8') as f:
        changelog_lines = f.read().strip()

    uuid.UUID(changelog_lines, version=4)
### tests/test_templates.py
"""
test_custom_extension_in_hooks.

Tests to ensure custom cookiecutter extensions are properly made available to
pre- and post-gen hooks.
"""

from pathlib import Path

import pytest

from cookiecutter import main


@pytest.fixture
def output_dir(tmpdir):
    """Fixture. Create and return custom temp directory for test."""
    return str(tmpdir.mkdir('templates'))


@pytest.mark.parametrize("template", ["include", "no-templates", "extends", "super"])
def test_build_templates(template, output_dir):
    """
    Verify Templates Design keywords.

    no-templates is a compatibility tests for repo without `templates` directory
    """
    project_dir = main.cookiecutter(
        f'tests/test-templates/{template}',
        no_input=True,
        output_dir=output_dir,
    )

    readme = Path(project_dir, 'requirements.txt').read_text()

    assert readme.split() == [
        "pip",
        "Click",
        "pytest",
    ]
### tests/test_cookiecutter_local_no_input.py
"""Test cookiecutter for work without any input.

Tests in this file execute `cookiecutter()` with `no_input=True` flag and
verify result with different settings in `cookiecutter.json`.
"""

import os
import textwrap
from pathlib import Path

import pytest

from cookiecutter import main, utils


@pytest.fixture(scope='function')
def remove_additional_dirs(request):
    """Fixture. Remove special directories which are created during the tests."""

    def fin_remove_additional_dirs():
        if os.path.isdir('fake-project'):
            utils.rmtree('fake-project')
        if os.path.isdir('fake-project-extra'):
            utils.rmtree('fake-project-extra')
        if os.path.isdir('fake-project-templated'):
            utils.rmtree('fake-project-templated')
        if os.path.isdir('fake-project-dict'):
            utils.rmtree('fake-project-dict')
        if os.path.isdir('fake-tmp'):
            utils.rmtree('fake-tmp')

    request.addfinalizer(fin_remove_additional_dirs)


@pytest.mark.parametrize('path', ['tests/fake-repo-pre/', 'tests/fake-repo-pre'])
@pytest.mark.usefixtures('clean_system', 'remove_additional_dirs')
def test_cookiecutter_no_input_return_project_dir(path):
    """Verify `cookiecutter` create project dir on input with or without slash."""
    project_dir = main.cookiecutter(path, no_input=True)
    assert os.path.isdir('tests/fake-repo-pre/{{cookiecutter.repo_name}}')
    assert not os.path.isdir('tests/fake-repo-pre/fake-project')
    assert os.path.isdir(project_dir)
    assert os.path.isfile('fake-project/README.rst')
    assert not os.path.exists('fake-project/json/')


@pytest.mark.usefixtures('clean_system', 'remove_additional_dirs')
def test_cookiecutter_no_input_extra_context():
    """Verify `cookiecutter` accept `extra_context` argument."""
    main.cookiecutter(
        'tests/fake-repo-pre',
        no_input=True,
        extra_context={'repo_name': 'fake-project-extra'},
    )
    assert os.path.isdir('fake-project-extra')


@pytest.mark.usefixtures('clean_system', 'remove_additional_dirs')
def test_cookiecutter_templated_context():
    """Verify Jinja2 templating correctly works in `cookiecutter.json` file."""
    main.cookiecutter('tests/fake-repo-tmpl', no_input=True)
    assert os.path.isdir('fake-project-templated')


@pytest.mark.usefixtures('clean_system', 'remove_additional_dirs')
def test_cookiecutter_no_input_return_rendered_file():
    """Verify Jinja2 templating correctly works in `cookiecutter.json` file."""
    project_dir = main.cookiecutter('tests/fake-repo-pre', no_input=True)
    assert project_dir == os.path.abspath('fake-project')
    content = Path(project_dir, 'README.rst').read_text()
    assert "Project name: **Fake Project**" in content


@pytest.mark.usefixtures('clean_system', 'remove_additional_dirs')
def test_cookiecutter_dict_values_in_context():
    """Verify configured dictionary from `cookiecutter.json` correctly unpacked."""
    project_dir = main.cookiecutter('tests/fake-repo-dict', no_input=True)
    assert project_dir == os.path.abspath('fake-project-dict')

    content = Path(project_dir, 'README.md').read_text()
    assert (
        content
        == textwrap.dedent(
            """
        # README


        <dl>
          <dt>Format name:</dt>
          <dd>Bitmap</dd>

          <dt>Extension:</dt>
          <dd>bmp</dd>

          <dt>Applications:</dt>
          <dd>
              <ul>
              <li>Paint</li>
              <li>GIMP</li>
              </ul>
          </dd>
        </dl>

        <dl>
          <dt>Format name:</dt>
          <dd>Portable Network Graphic</dd>

          <dt>Extension:</dt>
          <dd>png</dd>

          <dt>Applications:</dt>
          <dd>
              <ul>
              <li>GIMP</li>
              </ul>
          </dd>
        </dl>

    """
        ).lstrip()
    )


@pytest.mark.usefixtures('clean_system', 'remove_additional_dirs')
def test_cookiecutter_template_cleanup(mocker):
    """Verify temporary folder for zip unpacking dropped."""
    mocker.patch('tempfile.mkdtemp', return_value='fake-tmp', autospec=True)

    mocker.patch(
        'cookiecutter.prompt.prompt_and_delete', return_value=True, autospec=True
    )

    main.cookiecutter('tests/files/fake-repo-tmpl.zip', no_input=True)
    assert os.path.isdir('fake-project-templated')

    # The tmp directory will still exist, but the
    # extracted template directory *in* the temp directory will not.
    assert os.path.exists('fake-tmp')
    assert not os.path.exists('fake-tmp/fake-repo-tmpl')
### tests/test_cookiecutter_local_with_input.py
"""Test main cookiecutter invocation with user input enabled (mocked)."""

import os

import pytest

from cookiecutter import main, utils


@pytest.fixture(scope='function')
def remove_additional_dirs(request):
    """Remove special directories which are created during the tests."""
    yield
    if os.path.isdir('fake-project'):
        utils.rmtree('fake-project')
    if os.path.isdir('fake-project-input-extra'):
        utils.rmtree('fake-project-input-extra')


@pytest.mark.usefixtures('clean_system', 'remove_additional_dirs')
def test_cookiecutter_local_with_input(monkeypatch):
    """Verify simple cookiecutter run results, without extra_context provided."""
    monkeypatch.setattr(
        'cookiecutter.prompt.read_user_variable',
        lambda var, default, prompts, prefix: default,
    )
    main.cookiecutter('tests/fake-repo-pre/', no_input=False)
    assert os.path.isdir('tests/fake-repo-pre/{{cookiecutter.repo_name}}')
    assert not os.path.isdir('tests/fake-repo-pre/fake-project')
    assert os.path.isdir('fake-project')
    assert os.path.isfile('fake-project/README.rst')
    assert not os.path.exists('fake-project/json/')


@pytest.mark.usefixtures('clean_system', 'remove_additional_dirs')
def test_cookiecutter_input_extra_context(monkeypatch):
    """Verify simple cookiecutter run results, with extra_context provided."""
    monkeypatch.setattr(
        'cookiecutter.prompt.read_user_variable',
        lambda var, default, prompts, prefix: default,
    )
    main.cookiecutter(
        'tests/fake-repo-pre',
        no_input=False,
        extra_context={'repo_name': 'fake-project-input-extra'},
    )
    assert os.path.isdir('fake-project-input-extra')
### tests/conftest.py
"""pytest fixtures which are globally available throughout the suite."""

import os
import shutil

import pytest

from cookiecutter import utils
from cookiecutter.config import DEFAULT_CONFIG

USER_CONFIG = """
cookiecutters_dir: '{cookiecutters_dir}'
replay_dir: '{replay_dir}'
"""


@pytest.fixture(autouse=True)
def isolated_filesystem(monkeypatch, tmp_path):
    """Ensure filesystem isolation, set the user home to a tmp_path."""
    root_path = tmp_path.joinpath("home")
    root_path.mkdir()
    cookiecutters_dir = root_path.joinpath(".cookiecutters/")
    replay_dir = root_path.joinpath(".cookiecutter_replay/")
    monkeypatch.setitem(DEFAULT_CONFIG, 'cookiecutters_dir', str(cookiecutters_dir))
    monkeypatch.setitem(DEFAULT_CONFIG, 'replay_dir', str(replay_dir))

    monkeypatch.setenv("HOME", str(root_path))
    monkeypatch.setenv("USERPROFILE", str(root_path))


def backup_dir(original_dir, backup_dir):
    """Generate backup directory based on original directory."""
    # If the default original_dir is pre-existing, move it to a temp location
    if not os.path.isdir(original_dir):
        return False

    # Remove existing stale backups before backing up.
    if os.path.isdir(backup_dir):
        utils.rmtree(backup_dir)

    shutil.copytree(original_dir, backup_dir)
    return True


def restore_backup_dir(original_dir, backup_dir, original_dir_found):
    """Restore default contents."""
    original_dir_is_dir = os.path.isdir(original_dir)
    if original_dir_found:
        # Delete original_dir if a backup exists
        if original_dir_is_dir and os.path.isdir(backup_dir):
            utils.rmtree(original_dir)
    else:
        # Delete the created original_dir.
        # There's no backup because it never existed
        if original_dir_is_dir:
            utils.rmtree(original_dir)

    # Restore the user's default original_dir contents
    if os.path.isdir(backup_dir):
        shutil.copytree(backup_dir, original_dir)
    if os.path.isdir(original_dir):
        utils.rmtree(backup_dir)


@pytest.fixture(scope='function')
def clean_system(request):
    """Fixture. Simulates a clean system with no configured or cloned cookiecutters.

    It runs code which can be regarded as setup code as known from a unittest
    TestCase. Additionally it defines a local function referring to values
    which have been stored to local variables in the setup such as the location
    of the cookiecutters on disk. This function is registered as a teardown
    hook with `request.addfinalizer` at the very end of the fixture. Pytest
    runs the named hook as soon as the fixture is out of scope, when the test
    finished to put it another way.

    During setup:

    * Back up the `~/.cookiecutterrc` config file to `~/.cookiecutterrc.backup`
    * Back up the `~/.cookiecutters/` dir to `~/.cookiecutters.backup/`
    * Back up the `~/.cookiecutter_replay/` dir to
      `~/.cookiecutter_replay.backup/`
    * Starts off a test case with no pre-existing `~/.cookiecutterrc` or
      `~/.cookiecutters/` or `~/.cookiecutter_replay/`

    During teardown:

    * Delete `~/.cookiecutters/` only if a backup is present at
      `~/.cookiecutters.backup/`
    * Delete `~/.cookiecutter_replay/` only if a backup is present at
      `~/.cookiecutter_replay.backup/`
    * Restore the `~/.cookiecutterrc` config file from
      `~/.cookiecutterrc.backup`
    * Restore the `~/.cookiecutters/` dir from `~/.cookiecutters.backup/`
    * Restore the `~/.cookiecutter_replay/` dir from
      `~/.cookiecutter_replay.backup/`

    """
    # If ~/.cookiecutterrc is pre-existing, move it to a temp location
    user_config_path = os.path.expanduser('~/.cookiecutterrc')
    user_config_path_backup = os.path.expanduser('~/.cookiecutterrc.backup')
    if os.path.exists(user_config_path):
        user_config_found = True
        shutil.copy(user_config_path, user_config_path_backup)
        os.remove(user_config_path)
    else:
        user_config_found = False

    # If the default cookiecutters_dir is pre-existing, move it to a
    # temp location
    cookiecutters_dir = os.path.expanduser('~/.cookiecutters')
    cookiecutters_dir_backup = os.path.expanduser('~/.cookiecutters.backup')
    cookiecutters_dir_found = backup_dir(cookiecutters_dir, cookiecutters_dir_backup)

    # If the default cookiecutter_replay_dir is pre-existing, move it to a
    # temp location
    cookiecutter_replay_dir = os.path.expanduser('~/.cookiecutter_replay')
    cookiecutter_replay_dir_backup = os.path.expanduser('~/.cookiecutter_replay.backup')
    cookiecutter_replay_dir_found = backup_dir(
        cookiecutter_replay_dir, cookiecutter_replay_dir_backup
    )

    def restore_backup():
        # If it existed, restore ~/.cookiecutterrc
        # We never write to ~/.cookiecutterrc, so this logic is simpler.
        if user_config_found and os.path.exists(user_config_path_backup):
            shutil.copy(user_config_path_backup, user_config_path)
            os.remove(user_config_path_backup)

        # Carefully delete the created ~/.cookiecutters dir only in certain
        # conditions.
        restore_backup_dir(
            cookiecutters_dir, cookiecutters_dir_backup, cookiecutters_dir_found
        )

        # Carefully delete the created ~/.cookiecutter_replay dir only in
        # certain conditions.
        restore_backup_dir(
            cookiecutter_replay_dir,
            cookiecutter_replay_dir_backup,
            cookiecutter_replay_dir_found,
        )

    request.addfinalizer(restore_backup)


@pytest.fixture(scope='session')
def user_dir(tmp_path_factory):
    """Fixture that simulates the user's home directory."""
    return tmp_path_factory.mktemp('user_dir')


@pytest.fixture(scope='session')
def user_config_data(user_dir):
    """Fixture that creates 2 Cookiecutter user config dirs.

     It will create it in the user's home directory.

    * `cookiecutters_dir`
    * `cookiecutter_replay`

    :returns: Dict with name of both user config dirs
    """
    cookiecutters_dir = user_dir.joinpath('cookiecutters')
    cookiecutters_dir.mkdir()
    replay_dir = user_dir.joinpath('cookiecutter_replay')
    replay_dir.mkdir()
    return {
        'cookiecutters_dir': str(cookiecutters_dir),
        'replay_dir': str(replay_dir),
    }


@pytest.fixture(scope='session')
def user_config_file(user_dir, user_config_data):
    """Fixture that creates a config file called `config`.

     It will create it in the user's home directory, with YAML from
     `user_config_data`.

    :param user_dir: Simulated user's home directory
    :param user_config_data: Dict of config values
    :returns: String of path to config file
    """
    config_file = user_dir.joinpath('config')

    config_text = USER_CONFIG.format(**user_config_data)
    config_file.write_text(config_text)
    return str(config_file)


@pytest.fixture
def output_dir(tmp_path):
    """Fixture to prepare test output directory."""
    output_path = tmp_path.joinpath("output")
    output_path.mkdir()
    return str(output_path)


@pytest.fixture
def clone_dir(tmp_path):
    """Simulate creation of a directory called `clone_dir` inside of `tmp_path`. \
    Returns a str to said directory."""
    clone_dir = tmp_path.joinpath("clone_dir")
    clone_dir.mkdir()
    return clone_dir
[The command completed with exit code 0.]
[Current working directory: /workspace/cookiecutter]
[Python interpreter: /usr/bin/python]
[Command finished with exit code 0]