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