##// END OF EJS Templates
Print missing libraries and platform.
Thomas Kluyver -
Show More
@@ -1,141 +1,153 b''
1 1 """
2 2 This is a script for testing pull requests for IPython. It merges the pull
3 3 request with current master, installs and tests on all available versions of
4 4 Python, and posts the results to Gist if any tests fail.
5 5
6 6 Usage:
7 7 python test_pr.py 1657
8 8 """
9 9 from __future__ import print_function
10 10
11 11 import errno
12 12 from glob import glob
13 13 import json
14 14 import os
15 import re
15 16 import shutil
16 17 from subprocess import call, check_call, check_output, PIPE, STDOUT, CalledProcessError
17 18 try:
18 19 from urllib.request import urlopen
19 20 except ImportError:
20 21 from urllib2 import urlopen
21 22
22 23 basedir = os.path.join(os.path.expanduser("~"), ".ipy_pr_tests")
23 24 repodir = os.path.join(basedir, "ipython")
24 25 ipy_repository = 'git://github.com/ipython/ipython.git'
25 26
26 27 supported_pythons = ['python2.6', 'python2.7', 'python3.1', 'python3.2']
27 28 unavailable_pythons = []
28 29
29 30 def available_python_versions():
30 31 """Get the executable names of available versions of Python on the system.
31 32 """
32 33 del unavailable_pythons[:]
33 34 for py in supported_pythons:
34 35 try:
35 36 check_call([py, '-c', 'import nose'], stdout=PIPE)
36 37 yield py
37 38 except (OSError, CalledProcessError):
38 39 unavailable_pythons.append(py)
39 40
40 41 venvs = []
41 42
42 43 def setup():
43 44 """Prepare the repository and virtualenvs."""
44 45 global venvs
45 46
46 47 try:
47 48 os.mkdir(basedir)
48 49 except OSError as e:
49 50 if e.errno != errno.EEXIST:
50 51 raise
51 52 os.chdir(basedir)
52 53
53 54 # Delete virtualenvs and recreate
54 55 for venv in glob('venv-*'):
55 56 shutil.rmtree(venv)
56 57 for py in available_python_versions():
57 58 check_call(['virtualenv', '-p', py, '--system-site-packages', 'venv-%s' % py])
58 59 venvs.append((py, 'venv-%s' % py))
59 60
60 61 # Check out and update the repository
61 62 if not os.path.exists('ipython'):
62 63 check_call(['git', 'clone', ipy_repository])
63 64 os.chdir(repodir)
64 65 check_call(['git', 'checkout', 'master'])
65 66 check_call(['git', 'pull', ipy_repository, 'master'])
66 67 os.chdir(basedir)
67 68
68 69 def get_pull_request(num, project="ipython/ipython"):
69 70 url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=project, num=num)
70 71 response = urlopen(url).read().decode('utf-8')
71 72 return json.loads(response)
72 73
74 missing_libs_re = re.compile(r"Tools and libraries NOT available at test time:\n"
75 r"\s*(.*?)\n")
76 def get_missing_libraries(log):
77 m = missing_libs_re.search(log)
78 if m:
79 return m.group(1)
80
73 81 def merge_branch(repo, branch, owner):
74 82 merged_branch = "%s-%s" % (owner, branch)
75 83 os.chdir(repodir)
76 84 # Delete the branch first
77 85 call(['git', 'branch', '-D', merged_branch])
78 86 check_call(['git', 'checkout', '-b', merged_branch])
79 87 check_call(['git', 'pull', repo, branch])
80 88 os.chdir(basedir)
81 89
82 90 def run_tests(venv):
83 91 py = os.path.join(basedir, venv, 'bin', 'python')
84 92 print(py)
85 93 os.chdir(repodir)
86 94 check_call([py, 'setup.py', 'install'])
87 95 os.chdir(basedir)
88 96
89 97 iptest = os.path.join(basedir, venv, 'bin', 'iptest')
90 98 if not os.path.exists(iptest):
91 99 iptest = os.path.join(basedir, venv, 'bin', 'iptest3')
92 100
93 101 print("\nRunning tests, this typically takes a few minutes...")
94 102 try:
95 103 return True, check_output([iptest], stderr=STDOUT).decode('utf-8')
96 104 except CalledProcessError as e:
97 105 return False, e.output
98 106
99 107 def post_gist(content, description='IPython test log', filename="results.log"):
100 108 """Post some text to a Gist, and return the URL."""
101 109 post_data = json.dumps({
102 110 "description": description,
103 111 "public": True,
104 112 "files": {
105 113 filename: {
106 114 "content": content
107 115 }
108 116 }
109 117 }).encode('utf-8')
110 118
111 119 response = urlopen("https://api.github.com/gists", post_data)
112 120 response_data = json.loads(response.read().decode('utf-8'))
113 121 return response_data['html_url']
114 122
115 123 if __name__ == '__main__':
116 124 import sys
117 125 num = sys.argv[1]
118 126 setup()
119 127 pr = get_pull_request(num)
120 128 merge_branch(repo=pr['head']['repo']['clone_url'],
121 129 branch=pr['head']['ref'],
122 130 owner=pr['head']['repo']['owner']['login'])
123 131
124 132 results = []
125 133 for py, venv in venvs:
126 134 passed, log = run_tests(venv)
135 missing_libraries = get_missing_libraries(log)
127 136 if passed:
128 results.append((py, True, None))
137 results.append((py, True, None, missing_libraries))
129 138 else:
130 139 gist_url = post_gist(log)
131 results.append((py, False, gist_url))
140 results.append((py, False, gist_url, missing_libraries))
132 141
133 142 print("\n")
134 143 print("**Test results for commit %s merged into master**" % pr['head']['sha'][:7])
135 for py, passed, gist_url in results:
144 print("Platform:", sys.platform)
145 for py, passed, gist_url, missing_libraries in results:
136 146 if passed:
137 147 print(py, ":", "OK")
138 148 else:
139 149 print(py, ":", "Failed")
140 150 print(" Test log:", gist_url)
151 if missing_libraries:
152 print(" Libraries not available:", missing_libraries)
141 153 print("Not available for testing:", ", ".join(unavailable_pythons))
General Comments 0
You need to be logged in to leave comments. Login now