Completed
Pull Request — master (#961)
by
unknown
01:20
created

unzip()   D

Complexity

Conditions 8

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
c 1
b 0
f 0
dl 0
loc 46
rs 4.1666
1
from __future__ import absolute_import
2
3
import os
4
import requests
5
import sys
6
from zipfile import ZipFile
7
8
from .prompt import read_user_yes_no
9
from .utils import make_sure_path_exists, rmtree
10
11
12
def prompt_and_delete(path, no_input=False):
13
    """Ask the user whether it's okay to delete the previously-downloaded
14
    file/directory.
15
16
    If yes, deletes it. Otherwise, Cookiecutter exits.
17
18
    :param path: Previously downloaded zipfile.
19
    :param no_input: Suppress prompt to delete repo and just delete it.
20
    """
21
    # Suppress prompt if called via API
22
    if no_input:
23
        ok_to_delete = True
24
    else:
25
        question = (
26
            "You've downloaded {} before. "
27
            "Is it okay to delete and re-download it?"
28
        ).format(path)
29
30
        ok_to_delete = read_user_yes_no(question, 'yes')
31
32
    if ok_to_delete:
33
        if os.path.isdir(path):
34
            rmtree(path)
35
        else:
36
            os.remove(path)
37
    else:
38
        sys.exit()
39
40
    return ok_to_delete
41
42
43
def unzip(zip_url, is_url, clone_to_dir='.', no_input=False):
44
    # Ensure that clone_to_dir exists
45
    clone_to_dir = os.path.expanduser(clone_to_dir)
46
    make_sure_path_exists(clone_to_dir)
47
48
    if is_url:
49
        # Build the name of the cached zipfile,
50
        # and prompt to delete if it already exists.
51
        identifier = zip_url.rsplit('/', 1)[1]
52
        zip_path = os.path.join(clone_to_dir, identifier)
53
54
        if os.path.exists(zip_path):
55
            ok_to_delete = prompt_and_delete(zip_path, no_input=no_input)
56
        else:
57
            ok_to_delete = None
58
59
        # (Re) download the zipfile
60
        r = requests.get(zip_url, stream=True)
61
        with open(zip_path, 'wb') as f:
62
            for chunk in r.iter_content(chunk_size=1024):
63
                if chunk:  # filter out keep-alive new chunks
64
                    f.write(chunk)
65
    else:
66
        # Just use the local zipfile as-is.
67
        zip_path = os.path.abspath(zip_url)
68
        ok_to_delete = None
69
70
    # Now unpack the repository. The zipfile will include
71
    # the name of the template as the top level directory;
72
    # Check if that directory already exists, and if so,
73
    # prompt for deletion. If we've previously OK'd deletion,
74
    # don't ask again.
75
    zip_file = ZipFile(zip_path)
76
    unzip_name = zip_file.namelist()[0][:-1]
77
78
    unzip_path = os.path.join(clone_to_dir, unzip_name)
79
    if os.path.exists(unzip_path):
80
        if ok_to_delete is None:
81
            ok_to_delete = prompt_and_delete(unzip_path, no_input=no_input)
82
        else:
83
            rmtree(unzip_path)
84
85
    # Extract the zip file
86
    zip_file.extractall(path=clone_to_dir)
87
88
    return unzip_path
89