forked from scrapinghub/shub
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
181 lines (128 loc) · 5.21 KB
/
Copy pathutils.py
File metadata and controls
181 lines (128 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
from __future__ import unicode_literals
import importlib
import os
import subprocess
import sys
import re
from glob import glob
from os.path import isdir
from subprocess import Popen, PIPE, CalledProcessError
import requests
from click import ClickException
from shub.auth import find_api_key
from shub.click_utils import log
from shub.exceptions import AuthException
SCRAPY_CFG_FILE = os.path.expanduser("~/.scrapy.cfg")
FALLBACK_ENCODING = 'utf-8'
STDOUT_ENCODING = sys.stdout.encoding or FALLBACK_ENCODING
def missing_modules(*modules):
"""Receives a list of module names and returns those which are missing"""
missing = []
for module_name in modules:
try:
importlib.import_module(module_name)
except ImportError:
missing.append(module_name)
return missing
def make_deploy_request(url, data, files, auth):
try:
rsp = requests.post(url=url, auth=auth, data=data, files=files,
stream=True, timeout=300)
rsp.raise_for_status()
for line in rsp.iter_lines():
log(line)
return True
except requests.HTTPError as exc:
rsp = exc.response
if rsp.status_code == 403:
raise AuthException()
msg = "Deploy failed ({}):\n{}".format(rsp.status_code, rsp.text)
raise ClickException(msg)
except requests.RequestException as exc:
raise ClickException("Deploy failed: {}".format(exc))
def get_cmd_output(cmd):
return Popen(cmd, stdout=PIPE).communicate()[0].decode(STDOUT_ENCODING)
def pwd_git_version():
process = Popen(['git', 'describe', '--always'], stdout=PIPE)
commit_id = process.communicate()[0].decode(STDOUT_ENCODING).strip('\n')
if process.wait() != 0:
commit_id = get_cmd_output(['git', 'rev-list', '--count', 'HEAD']).strip('\n')
branch = get_cmd_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).strip('\n')
return '%s-%s' % (commit_id, branch)
def pwd_hg_version():
commit_id = 'r%s' % get_cmd_output(['hg', 'tip', '--template', '{rev}'])
branch = get_cmd_output(['hg', 'branch']).strip('\n')
return '%s-%s' % (commit_id, branch)
def pwd_bzr_version():
return '%s' % get_cmd_output(['bzr', 'revno']).strip()
def run(cmd):
output = subprocess.check_output(cmd, shell=True)
return output.decode(STDOUT_ENCODING).strip()
def decompress_egg_files():
decompressor_by_ext = _build_decompressor_by_ext_map()
eggs = [f for ext in decompressor_by_ext for f in glob('*.%s' % ext)]
if not eggs:
files = glob('*')
err = ('No egg files with a supported file extension were found. '
'Files: %s' % ', '.join(files))
raise ClickException(err)
for egg in eggs:
log("Uncompressing: %s" % egg)
run("%s %s" % (decompressor_by_ext[_ext(egg)], egg))
def build_and_deploy_eggs(project_id, apikey):
egg_dirs = (f for f in glob('*') if isdir(f))
for egg_dir in egg_dirs:
os.chdir(egg_dir)
build_and_deploy_egg(project_id, apikey)
os.chdir('..')
def _build_decompressor_by_ext_map():
unzip = 'unzip -q'
return {'zip': unzip,
'whl': unzip,
'bz2': 'tar jxf',
'gz': 'tar zxf'}
def _ext(file_path):
return os.path.splitext(file_path)[1].strip('.')
def build_and_deploy_egg(project_id, apikey):
"""Builds and deploys the current dir's egg"""
log("Building egg in: %s" % os.getcwd())
try:
run('python setup.py bdist_egg')
except CalledProcessError:
# maybe a C extension or distutils package, forcing bdist_egg
log("Couldn't build an egg with vanilla setup.py, trying with setuptools...")
run('python -c "import setuptools; __file__=\'setup.py\'; execfile(\'setup.py\')" bdist_egg')
_deploy_dependency_egg(apikey, project_id)
def _deploy_dependency_egg(apikey, project_id):
name = _get_dependency_name()
version = _get_dependency_version(name)
egg_name, egg_path = _get_egg_info(name)
url = 'https://dash.scrapinghub.com/api/eggs/add.json'
data = {'project': project_id, 'name': name, 'version': version}
files = {'egg': (egg_name, open(egg_path, 'rb'))}
auth = (apikey, '')
log('Deploying dependency to Scrapy Cloud project "%s"' % project_id)
make_deploy_request(url, data, files, auth)
success = "Deployed eggs list at: https://dash.scrapinghub.com/p/%s/eggs"
log(success % project_id)
def _last_line_of(s):
return s.split('\n')[-1]
def _get_dependency_name():
# In some cases, python setup.py --name returns more than one line, so we use the last one to get the name
return _last_line_of(run('python setup.py --name'))
def _get_dependency_version(name):
if isdir('.git'):
return pwd_git_version()
elif isdir('.hg'):
return pwd_hg_version()
elif isdir('.bzr'):
return pwd_bzr_version()
version = _last_line_of(run('python setup.py --version'))
return "%s-%s" % (name, version)
def _get_egg_info(name):
egg_filename = name.replace('-', '_')
egg_path_glob = os.path.join('dist', '%s*' % egg_filename)
egg_path = glob(egg_path_glob)[0]
return (egg_filename, egg_path)
def is_valid_jobid(jobid):
return bool(re.match(r'\d+/\d+/\d+$', jobid))