Completed
Push — 629-preserve-existing-director... ( c055a4 )
by Michael
30s
created

fin_remove_additional_folders()   B

Complexity

Conditions 5

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
dl 0
loc 9
rs 8.5454
c 1
b 0
f 0
1
# -*- coding: utf-8 -*-
2
3
"""
4
test_generate_hooks
5
-------------------
6
7
Tests formerly known from a unittest residing in test_generate.py named
8
TestHooks.test_ignore_hooks_dirs
9
TestHooks.test_run_python_hooks
10
TestHooks.test_run_python_hooks_cwd
11
TestHooks.test_run_shell_hooks
12
"""
13
14
from __future__ import unicode_literals
15
import errno
16
import os
17
import sys
18
import stat
19
import pytest
20
21
from cookiecutter import generate
22
from cookiecutter import utils
23
from cookiecutter.exceptions import FailedHookException
24
25
WINDOWS = sys.platform.startswith('win')
26
27
28
@pytest.fixture(scope='function')
29
def remove_additional_folders(request):
30
    """
31
    Remove some special folders which are created by the tests.
32
    """
33
    def fin_remove_additional_folders():
34
        if os.path.exists('tests/test-pyhooks/inputpyhooks'):
35
            utils.rmtree('tests/test-pyhooks/inputpyhooks')
36
        if os.path.exists('inputpyhooks'):
37
            utils.rmtree('inputpyhooks')
38
        if os.path.exists('tests/test-shellhooks'):
39
            utils.rmtree('tests/test-shellhooks')
40
        if os.path.exists('tests/test-hooks'):
41
            utils.rmtree('tests/test-hooks')
42
    request.addfinalizer(fin_remove_additional_folders)
43
44
45
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
46
def test_ignore_hooks_dirs():
47
    generate.generate_files(
48
        context={
49
            'cookiecutter': {'pyhooks': 'pyhooks'}
50
        },
51
        repo_dir='tests/test-pyhooks/',
52
        output_dir='tests/test-pyhooks/'
53
    )
54
    assert not os.path.exists('tests/test-pyhooks/inputpyhooks/hooks')
55
56
57
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
58
def test_run_python_hooks():
59
    generate.generate_files(
60
        context={
61
            'cookiecutter': {'pyhooks': 'pyhooks'}
62
        },
63
        repo_dir='tests/test-pyhooks/'.replace("/", os.sep),
64
        output_dir='tests/test-pyhooks/'.replace("/", os.sep)
65
    )
66
    assert os.path.exists('tests/test-pyhooks/inputpyhooks/python_pre.txt')
67
    assert os.path.exists('tests/test-pyhooks/inputpyhooks/python_post.txt')
68
69
70
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
71
def test_run_python_hooks_cwd():
72
    generate.generate_files(
73
        context={
74
            'cookiecutter': {'pyhooks': 'pyhooks'}
75
        },
76
        repo_dir='tests/test-pyhooks/'
77
    )
78
    assert os.path.exists('inputpyhooks/python_pre.txt')
79
    assert os.path.exists('inputpyhooks/python_post.txt')
80
81
82
@pytest.mark.skipif(WINDOWS, reason='OSError.errno=8 is not thrown on Windows')
83
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
84
def test_empty_hooks():
85
    # OSError.errno=8 is not thrown on Windows when the script is empty
86
    # because it always runs through shell instead of needing a shebang.
87
    with pytest.raises(FailedHookException) as excinfo:
88
        generate.generate_files(
89
            context={
90
                'cookiecutter': {'shellhooks': 'shellhooks'}
91
            },
92
            repo_dir='tests/test-shellhooks-empty/',
93
            overwrite_if_exists=True
94
        )
95
    assert 'shebang' in str(excinfo.value)
96
97
98
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
99
def test_oserror_hooks(mocker):
100
101
    message = 'Out of memory'
102
103
    err = OSError(message)
104
    err.errno = errno.ENOMEM
105
106
    prompt = mocker.patch('subprocess.Popen')
107
    prompt.side_effect = err
108
109
    os.makedirs('inputshellhooks')
110
    with pytest.raises(FailedHookException) as excinfo:
111
        generate.generate_files(
112
            context={
113
                'cookiecutter': {'shellhooks': 'shellhooks'}
114
            },
115
            repo_dir='tests/test-shellhooks-empty/',
116
            overwrite_if_exists=True
117
        )
118
    assert message in str(excinfo.value)
119
    assert os.path.exists('inputshellhooks')
120
121
122 View Code Duplication
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
123
def test_run_failing_hook_cleansup():
124
    repo_path = os.path.abspath('tests/test-hooks/')
125
    hooks_path = os.path.abspath('tests/test-hooks/hooks')
126
127
    hook_dir = os.path.join(repo_path, 'hooks')
128
    template = os.path.join(repo_path, 'input{{cookiecutter.hooks}}')
129
    os.mkdir(repo_path)
130
    os.mkdir(hook_dir)
131
    os.mkdir(template)
132
133
    hook_path = os.path.join(hooks_path, 'pre_gen_project.py')
134
135
    with open(hook_path, 'w') as f:
136
        f.write(b"#!/usr/bin/env python\n")
137
        f.write(b"import sys; sys.exit(1)\n")
138
139
    with pytest.raises(FailedHookException) as excinfo:
140
        generate.generate_files(
141
            context={
142
                'cookiecutter': {'hooks': 'hooks'}
143
            },
144
            repo_dir='tests/test-hooks/',
145
            overwrite_if_exists=True
146
        )
147
        assert 'Hook script failed' in str(excinfo.value)
148
    assert not os.path.exists('inputhooks')
149
150
151 View Code Duplication
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
152
def test_run_failing_hook_preserves_existing_output_directory():
153
    repo_path = os.path.abspath('tests/test-hooks/')
154
    hooks_path = os.path.abspath('tests/test-hooks/hooks')
155
156
    hook_dir = os.path.join(repo_path, 'hooks')
157
    template = os.path.join(repo_path, 'input{{cookiecutter.hooks}}')
158
    os.mkdir(repo_path)
159
    os.mkdir(hook_dir)
160
    os.mkdir(template)
161
162
    hook_path = os.path.join(hooks_path, 'pre_gen_project.py')
163
164
    with open(hook_path, 'w') as f:
165
        f.write(b"#!/usr/bin/env python\n")
166
        f.write(b"import sys; sys.exit(1)\n")
167
168
    os.mkdir('inputhooks')
169
    with pytest.raises(FailedHookException) as excinfo:
170
        generate.generate_files(
171
            context={
172
                'cookiecutter': {'hooks': 'hooks'}
173
            },
174
            repo_dir='tests/test-hooks/',
175
            overwrite_if_exists=True
176
        )
177
        assert 'Hook script failed' in str(excinfo.value)
178
    assert os.path.exists('inputhooks')
179
180
181
def make_test_repo(name):
182
    hooks = os.path.join(name, 'hooks')
183
    template = os.path.join(name, 'input{{cookiecutter.shellhooks}}')
184
    os.mkdir(name)
185
    os.mkdir(hooks)
186
    os.mkdir(template)
187
188
    with open(os.path.join(template, 'README.rst'), 'w') as f:
189
        f.write("foo\n===\n\nbar\n")
190
191
    if sys.platform.startswith('win'):
192
        filename = os.path.join(hooks, 'pre_gen_project.bat')
193
        with open(filename, 'w') as f:
194
            f.write("@echo off\n")
195
            f.write("\n")
196
            f.write("echo pre generation hook\n")
197
            f.write("echo. >shell_pre.txt\n")
198
199
        filename = os.path.join(hooks, 'post_gen_project.bat')
200
        with open(filename, 'w') as f:
201
            f.write("@echo off\n")
202
            f.write("\n")
203
            f.write("echo post generation hook\n")
204
            f.write("echo. >shell_post.txt\n")
205
    else:
206
        filename = os.path.join(hooks, 'pre_gen_project.sh')
207
        with open(filename, 'w') as f:
208
            f.write("#!/bin/bash\n")
209
            f.write("\n")
210
            f.write("echo 'pre generation hook';\n")
211
            f.write("touch 'shell_pre.txt'\n")
212
        # Set the execute bit
213
        os.chmod(filename, os.stat(filename).st_mode | stat.S_IXUSR)
214
215
        filename = os.path.join(hooks, 'post_gen_project.sh')
216
        with open(filename, 'w') as f:
217
            f.write("#!/bin/bash\n")
218
            f.write("\n")
219
            f.write("echo 'post generation hook';\n")
220
            f.write("touch 'shell_post.txt'\n")
221
        # Set the execute bit
222
        os.chmod(filename, os.stat(filename).st_mode | stat.S_IXUSR)
223
224
225
@pytest.mark.usefixtures('clean_system', 'remove_additional_folders')
226
def test_run_shell_hooks():
227
    make_test_repo('tests/test-shellhooks')
228
    generate.generate_files(
229
        context={
230
            'cookiecutter': {'shellhooks': 'shellhooks'}
231
        },
232
        repo_dir='tests/test-shellhooks/',
233
        output_dir='tests/test-shellhooks/'
234
    )
235
    shell_pre_file = 'tests/test-shellhooks/inputshellhooks/shell_pre.txt'
236
    shell_post_file = 'tests/test-shellhooks/inputshellhooks/shell_post.txt'
237
    assert os.path.exists(shell_pre_file)
238
    assert os.path.exists(shell_post_file)
239