Downloader   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 86
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 86
rs 10
wmc 21

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __call__() 0 4 1
A __init__() 0 4 1
A download_files() 0 9 3
B download() 0 18 5
D list_files() 0 27 8
A ensure_output() 0 6 2
A can_download() 0 8 1
1
import os
2
from time import mktime
3
from dateutil.parser import parse
4
from binstar_client.errors import DestionationPathExists
5
6
7
class Downloader(object):
8
    """
9
    Download notebook from your Anaconda repository.
10
    """
11
    def __init__(self, aserver_api, username, notebook):
12
        self.aserver_api = aserver_api
13
        self.username = username
14
        self.notebook = notebook
15
16
    def __call__(self, output='.', force=False):
17
        self.output = output
18
        self.ensure_output()
19
        return self.download_files(force)
20
21
    def download_files(self, force=False):
22
        output = []
23
        for f in self.list_files():
24
            if self.can_download(f, force):
25
                self.download(f)
26
                output.append(f['basename'])
27
            else:
28
                raise DestionationPathExists(f['basename'])
29
        return output
30
31
    def download(self, dist):
32
        """
33
        Download file into location
34
        """
35
        filename = dist['basename']
36
        requests_handle = self.aserver_api.download(
37
            self.username, self.notebook, dist['version'], filename
38
        )
39
40
        if not os.path.exists(os.path.dirname(filename)):
41
            try:
42
                os.makedirs(os.path.dirname(filename))
43
            except OSError:
44
                pass
45
46
        with open(os.path.join(self.output, filename), 'wb') as fdout:
47
            for chunk in requests_handle.iter_content(4096):
48
                fdout.write(chunk)
49
50
    def can_download(self, dist, force=False):
51
        """
52
        Can download if location/file does not exist or if force=True
53
        :param dist:
54
        :param force:
55
        :return: True/False
56
        """
57
        return not os.path.exists(os.path.join(self.output, dist['basename'])) or force
58
59
    def ensure_output(self):
60
        """
61
        Ensure output's directory exists
62
        """
63
        if not os.path.exists(self.output):
64
            os.makedirs(self.output)
65
66
    def list_files(self):
67
        """
68
        List available files in a project (aka notebook)
69
        :return: list
70
        """
71
        output = []
72
        tmp = {}
73
74
        files = self.aserver_api.package(self.username, self.notebook)['files']
75
76
        for f in files:
77
            if f['basename'] in tmp:
78
                tmp[f['basename']].append(f)
79
            else:
80
                tmp[f['basename']] = [f]
81
82
        for basename, versions in tmp.items():
83
            try:
84
                output.append(max(versions, key=lambda x: int(x['version'])))
85
            except ValueError:
86
                output.append(
87
                    max(versions, key=lambda x: mktime(parse(x['upload_time']).timetuple()))
88
                )
89
            except:
90
                output.append(versions[-1])
91
92
        return output
93