forked from trentm/cmdln
-
Notifications
You must be signed in to change notification settings - Fork 2
/
toxbootstrap.py
154 lines (114 loc) · 4.77 KB
/
toxbootstrap.py
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
#!/usr/bin/env python
# Find the latest version of this script at:
# http://github.com/srid/tox-bootstrap/raw/master/toxbootstrap.py
import sys
import os
from os import path
import logging
from subprocess import Popen, PIPE, check_call, CalledProcessError
PY3 = sys.version_info[0] == 3
if PY3:
from urllib.request import urlretrieve
import xmlrpc.client as xmlrpclib
else:
from urllib import urlretrieve
import xmlrpclib
logging.basicConfig(level=logging.INFO)
# Last stable: 1.4.9
VIRTUALENVPY_URL = 'http://bitbucket.org/ianb/virtualenv/raw/6d187b9cf916/virtualenv.py'
def run(cmd, shell=True):
"""Run the given command in shell"""
logging.info('Running command: %s', cmd)
check_call(cmd, shell=shell)
def crun(cmd, shell=True):
"""Run the given command and return its output"""
logging.info('Running command (for output): %s', cmd)
p = Popen(cmd, stdout=PIPE, shell=shell)
stdout, stderr = p.communicate()
return stdout
def wget(url):
"""Download the given file to current directory"""
logging.info('Downloading %s', url)
localpath = path.join(path.abspath(os.getcwd()), path.basename(url))
urlretrieve(url, localpath)
def has_script(venv, name):
"""Check if the virtualenv has the given script
Looks for bin/$name (unix) or Scripts/$name.exe (windows) in the virtualenv
"""
if sys.platform == 'win32':
return any([path.exists(path.join(venv, 'Scripts', name)),
path.exists(path.join(venv, 'Scripts', name + '.exe'))])
else:
return path.exists(path.join(venv, 'bin', name))
def get_script_path(venv, name):
"""Return the full path to the script in virtualenv directory"""
if sys.platform == 'win32':
p = path.join(venv, 'Scripts', name)
if not path.exists(p):
p = path.join(venv, 'Scripts', name + '.exe')
else:
p = path.join(venv, 'bin', name)
if not path.exists(p):
raise NameError('cannot find a script named "%s"' % (name,))
return p
def get_tox_version(venv):
"""Return the installed version of tox"""
py = get_script_path(venv, 'python')
s = 'import tox,sys; sys.stdout.write(str(tox.__version__))'
return crun('%s -s -c "%s"' % (py, s))
def parse_simple_version(v):
"""A simplified version of pkg_resources.parse_version
This method can only parse simple versions like the ones with a set of
numbers separated by dots (eg: 1.2.3)
"""
return [int(c) for c in v.split('.')]
def pypi_get_latest_version(pkgname):
"""Return the latest version of package from PyPI"""
pypi = xmlrpclib.ServerProxy('http://pypi.python.org/pypi')
versions = pypi.package_releases('tox')
assert versions
versions.sort(key=parse_simple_version, reverse=True)
return versions[0]
def cmdline(argv=None):
os.chdir(path.abspath(path.dirname(__file__)))
if not path.isdir('.tox'):
os.mkdir('.tox')
os.chdir('.tox')
# create virtual environment
if not path.isdir('toxinstall') or not has_script('toxinstall', 'python'):
# get virtualenv.py
if not path.isfile('virtualenv.py'):
wget(VIRTUALENVPY_URL)
assert path.isfile('virtualenv.py')
# XXX: we use --no-site-packages because: if tox is installed in global
# site-packages, then pip will not install it locally. ideal fix for
# this should be to first look for tox in the global scripts/ directory
run('python virtualenv.py --no-site-packages --distribute toxinstall')
assert has_script('toxinstall', 'python'), 'no python script'
assert has_script('toxinstall', 'pip'), 'no pip script'
pip = get_script_path('toxinstall', 'pip')
# install/upgrade tox itself
if any([
not has_script('toxinstall', 'tox'),
get_tox_version('toxinstall') != pypi_get_latest_version('tox')]):
run('%s install --upgrade --download-cache=pip-cache tox' % (pip,))
assert has_script('toxinstall', 'tox')
tox_script = path.abspath(get_script_path('toxinstall', 'tox'))
logging.info('tox is already installed at %s', tox_script)
virtualenv = get_script_path('toxinstall', 'virtualenv')
# XXX: virtualenv 1.5 is broken; replace it
if crun('%s --version' % (virtualenv,)).strip() == '1.5':
logging.info(
'Replacing the unstable virtualenv-1.5 with the latest stable')
run('%s uninstall -y virtualenv' % (pip,))
run('%s install virtualenv!=1.5' % (pip,))
# Now run the locally-installed tox
os.chdir('..')
try:
run([tox_script] + (argv or []), shell=False)
except CalledProcessError:
_, e, _ = sys.exc_info()
logging.error('tox exited with error code %d', e.returncode)
sys.exit(e.returncode)
if __name__ == '__main__':
cmdline(sys.argv[1:])