Passed
Push — master ( c48119...a6113e )
by
unknown
02:32 queued 01:20
created

tests.conftest.output_dir()   A

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
"""pytest fixtures which are globally available throughout the suite."""
2
import os
3
import shutil
4
5
import pytest
6
7
from cookiecutter import utils
8
9
10
USER_CONFIG = """
11
cookiecutters_dir: '{cookiecutters_dir}'
12
replay_dir: '{replay_dir}'
13
"""
14
# In YAML, double quotes mean to use escape sequences.
15
# Single quotes mean we will have unescaped backslahes.
16
# http://blogs.perl.org/users/tinita/2018/03/
17
# strings-in-yaml---to-quote-or-not-to-quote.html
18
19
20
def backup_dir(original_dir, backup_dir):
21
    """Generate backup directory based on original directory."""
22
    # If the default original_dir is pre-existing, move it to a temp location
23
    if not os.path.isdir(original_dir):
24
        return False
25
26
    # Remove existing backups before backing up. If they exist, they're stale.
27
    if os.path.isdir(backup_dir):
28
        utils.rmtree(backup_dir)
29
30
    shutil.copytree(original_dir, backup_dir)
31
    return True
32
33
34
def restore_backup_dir(original_dir, backup_dir, original_dir_found):
35
    """Restore default contents."""
36
    # Carefully delete the created original_dir only in certain
37
    # conditions.
38
    original_dir_is_dir = os.path.isdir(original_dir)
39
    if original_dir_found:
40
        # Delete the created original_dir as long as a backup
41
        # exists
42
        if original_dir_is_dir and os.path.isdir(backup_dir):
43
            utils.rmtree(original_dir)
44
    else:
45
        # Delete the created original_dir.
46
        # There's no backup because it never existed
47
        if original_dir_is_dir:
48
            utils.rmtree(original_dir)
49
50
    # Restore the user's default original_dir contents
51
    if os.path.isdir(backup_dir):
52
        shutil.copytree(backup_dir, original_dir)
53
    if os.path.isdir(original_dir):
54
        utils.rmtree(backup_dir)
55
56
57
@pytest.fixture(scope='function')
58
def clean_system(request):
59
    """Fixture. Simulates a clean system with no configured or cloned cookiecutters.
60
61
    It runs code which can be regarded as setup code as known from a unittest
62
    TestCase. Additionally it defines a local function referring to values
63
    which have been stored to local variables in the setup such as the location
64
    of the cookiecutters on disk. This function is registered as a teardown
65
    hook with `request.addfinalizer` at the very end of the fixture. Pytest
66
    runs the named hook as soon as the fixture is out of scope, when the test
67
    finished to put it another way.
68
69
    During setup:
70
71
    * Back up the `~/.cookiecutterrc` config file to `~/.cookiecutterrc.backup`
72
    * Back up the `~/.cookiecutters/` dir to `~/.cookiecutters.backup/`
73
    * Back up the `~/.cookiecutter_replay/` dir to
74
      `~/.cookiecutter_replay.backup/`
75
    * Starts off a test case with no pre-existing `~/.cookiecutterrc` or
76
      `~/.cookiecutters/` or `~/.cookiecutter_replay/`
77
78
    During teardown:
79
80
    * Delete `~/.cookiecutters/` only if a backup is present at
81
      `~/.cookiecutters.backup/`
82
    * Delete `~/.cookiecutter_replay/` only if a backup is present at
83
      `~/.cookiecutter_replay.backup/`
84
    * Restore the `~/.cookiecutterrc` config file from
85
      `~/.cookiecutterrc.backup`
86
    * Restore the `~/.cookiecutters/` dir from `~/.cookiecutters.backup/`
87
    * Restore the `~/.cookiecutter_replay/` dir from
88
      `~/.cookiecutter_replay.backup/`
89
90
    """
91
    # If ~/.cookiecutterrc is pre-existing, move it to a temp location
92
    user_config_path = os.path.expanduser('~/.cookiecutterrc')
93
    user_config_path_backup = os.path.expanduser('~/.cookiecutterrc.backup')
94
    if os.path.exists(user_config_path):
95
        user_config_found = True
96
        shutil.copy(user_config_path, user_config_path_backup)
97
        os.remove(user_config_path)
98
    else:
99
        user_config_found = False
100
101
    # If the default cookiecutters_dir is pre-existing, move it to a
102
    # temp location
103
    cookiecutters_dir = os.path.expanduser('~/.cookiecutters')
104
    cookiecutters_dir_backup = os.path.expanduser('~/.cookiecutters.backup')
105
    cookiecutters_dir_found = backup_dir(cookiecutters_dir, cookiecutters_dir_backup)
106
107
    # If the default cookiecutter_replay_dir is pre-existing, move it to a
108
    # temp location
109
    cookiecutter_replay_dir = os.path.expanduser('~/.cookiecutter_replay')
110
    cookiecutter_replay_dir_backup = os.path.expanduser('~/.cookiecutter_replay.backup')
111
    cookiecutter_replay_dir_found = backup_dir(
112
        cookiecutter_replay_dir, cookiecutter_replay_dir_backup
113
    )
114
115
    def restore_backup():
116
        # If it existed, restore ~/.cookiecutterrc
117
        # We never write to ~/.cookiecutterrc, so this logic is simpler.
118
        if user_config_found and os.path.exists(user_config_path_backup):
119
            shutil.copy(user_config_path_backup, user_config_path)
120
            os.remove(user_config_path_backup)
121
122
        # Carefully delete the created ~/.cookiecutters dir only in certain
123
        # conditions.
124
        restore_backup_dir(
125
            cookiecutters_dir, cookiecutters_dir_backup, cookiecutters_dir_found
126
        )
127
128
        # Carefully delete the created ~/.cookiecutter_replay dir only in
129
        # certain conditions.
130
        restore_backup_dir(
131
            cookiecutter_replay_dir,
132
            cookiecutter_replay_dir_backup,
133
            cookiecutter_replay_dir_found,
134
        )
135
136
    request.addfinalizer(restore_backup)
137
138
139
@pytest.fixture(scope='session')
140
def user_dir(tmp_path_factory):
141
    """Fixture that simulates the user's home directory."""
142
    return tmp_path_factory.mktemp('user_dir')
143
144
145
@pytest.fixture(scope='session')
146
def user_config_data(user_dir):
147
    """Fixture that creates 2 Cookiecutter user config dirs.
148
149
     It will create it in the user's home directory.
150
151
    * `cookiecutters_dir`
152
    * `cookiecutter_replay`
153
154
    :returns: Dict with name of both user config dirs
155
    """
156
    cookiecutters_dir = user_dir.joinpath('cookiecutters')
157
    cookiecutters_dir.mkdir()
158
    replay_dir = user_dir.joinpath('cookiecutter_replay')
159
    replay_dir.mkdir()
160
    return {
161
        'cookiecutters_dir': str(cookiecutters_dir),
162
        'replay_dir': str(replay_dir),
163
    }
164
165
166
@pytest.fixture(scope='session')
167
def user_config_file(user_dir, user_config_data):
168
    """Fixture that creates a config file called `config`.
169
170
     It will create it in the user's home directory, with YAML from
171
     `user_config_data`.
172
173
    :param user_dir: Simulated user's home directory
174
    :param user_config_data: Dict of config values
175
    :returns: String of path to config file
176
    """
177
    config_file = user_dir.joinpath('config')
178
179
    config_text = USER_CONFIG.format(**user_config_data)
180
    config_file.write_text(config_text)
181
    return str(config_file)
182
183
184
@pytest.fixture
185
def output_dir(tmp_path):
186
    """Fixture to prepare test output directory."""
187
    output_path = tmp_path.joinpath("output")
188
    output_path.mkdir()
189
    return str(output_path)
190
191
192
@pytest.fixture
193
def clone_dir(tmp_path):
194
    """Simulate creation of a directory called `clone_dir` inside of `tmp_path`. \
195
    Returns a str to said directory."""
196
    clone_dir = tmp_path.joinpath("clone_dir")
197
    clone_dir.mkdir()
198
    return clone_dir
199