1
|
|
|
from tempfile import SpooledTemporaryFile |
2
|
|
|
import requests |
3
|
|
|
import binstar_client |
4
|
|
|
from binstar_client.requests_ext import stream_multipart |
5
|
|
|
from binstar_client.utils import compute_hash, jencode |
6
|
|
|
|
7
|
|
|
|
8
|
|
|
class ProjectUploader(binstar_client.Binstar): |
9
|
|
|
def __init__(self, token, **kwargs): |
10
|
|
|
domain = kwargs.get('domain', 'https://api.anaconda.org') |
11
|
|
|
verify = kwargs.get('verify', True) |
12
|
|
|
self.username = kwargs.get('username', None) |
13
|
|
|
self.project = kwargs.get('project', None) |
14
|
|
|
super(ProjectUploader, self).__init__(token, domain, verify) |
15
|
|
|
|
16
|
|
|
def exists(self): |
17
|
|
|
url = "{}/apps/{}/projects/{}".format( |
18
|
|
|
self.domain, self.username, self.project.name) |
19
|
|
|
res = self.session.get(url) |
20
|
|
|
return res.status_code == 200 |
21
|
|
|
|
22
|
|
|
def create(self): |
23
|
|
|
url = "{}/apps/{}/projects".format(self.domain, self.username) |
24
|
|
|
data, headers = jencode(self.project.to_project_creation()) |
25
|
|
|
res = self.session.post(url, data=data, headers=headers) |
26
|
|
|
return res |
27
|
|
|
|
28
|
|
|
def stage(self): |
29
|
|
|
url = "{}/apps/{}/projects/{}/stage".format( |
30
|
|
|
self.domain, self.username, self.project.name) |
31
|
|
|
data, headers = jencode(self.project.to_stage()) |
32
|
|
|
res = self.session.post(url, data=data, headers=headers) |
33
|
|
|
self._check_response(res) |
34
|
|
|
return res |
35
|
|
|
|
36
|
|
|
def commit(self, revision_id): |
37
|
|
|
url = "{}/apps/{}/projects/{}/commit/{}".format( |
38
|
|
|
self.domain, self.username, |
39
|
|
|
self.project.name, revision_id |
40
|
|
|
) |
41
|
|
|
data, headers = jencode({}) |
42
|
|
|
res = self.session.post(url, data=data, headers=headers) |
43
|
|
|
self._check_response(res, [201]) |
44
|
|
|
return res |
45
|
|
|
|
46
|
|
|
def file_upload(self, url, obj): |
47
|
|
|
_hexmd5, b64md5, size = compute_hash( |
48
|
|
|
self.project.tar, size=self.project.size) |
49
|
|
|
|
50
|
|
|
s3data = obj['form_data'] |
51
|
|
|
s3data['Content-Length'] = size |
52
|
|
|
s3data['Content-MD5'] = b64md5 |
53
|
|
|
|
54
|
|
|
data_stream, headers = stream_multipart( |
55
|
|
|
s3data, files={'file': (self.project.basename, self.project.tar)}) |
56
|
|
|
|
57
|
|
|
s3res = requests.post( |
58
|
|
|
url, |
59
|
|
|
data=data_stream, |
60
|
|
|
verify=self.session.verify, |
61
|
|
|
timeout=10 * 60 * 60, |
62
|
|
|
headers=headers) |
63
|
|
|
|
64
|
|
|
if s3res.status_code != 201: |
65
|
|
|
raise binstar_client.errors.BinstarError( |
66
|
|
|
'Error uploading package', s3res.status_code) |
67
|
|
|
return s3res |
68
|
|
|
|
69
|
|
|
def projects(self): |
70
|
|
|
url = "{}/apps/{}/projects".format(self.domain, self.username) |
71
|
|
|
data, headers = jencode(self.project.to_project_creation()) |
72
|
|
|
return self.session.get(url, data=data, headers=headers) |
73
|
|
|
|
74
|
|
|
def upload(self): |
75
|
|
|
''' |
76
|
|
|
* Check if project already exists |
77
|
|
|
* if it doesn't, then create it |
78
|
|
|
* stage a new revision |
79
|
|
|
* upload |
80
|
|
|
* commit revision |
81
|
|
|
''' |
82
|
|
|
if not self.exists(): |
83
|
|
|
self.create() |
84
|
|
|
|
85
|
|
|
data = self.stage().json() |
86
|
|
|
self.file_upload(data['post_url'], data) |
87
|
|
|
res = self.commit(data['dist_id']) |
88
|
|
|
data = res.json() |
89
|
|
|
return data |
90
|
|
|
|