提交 cc37d22d authored 作者: nouiz's avatar nouiz

Merge pull request #716 from nouiz/small

Small
...@@ -495,6 +495,8 @@ Theano dependencies is easy, but be aware that it will take a long time ...@@ -495,6 +495,8 @@ Theano dependencies is easy, but be aware that it will take a long time
- MacPorts requires installing XCode first (which can be found in the - MacPorts requires installing XCode first (which can be found in the
Mac App Store), if you do not have it already. Mac App Store), if you do not have it already.
If you can't install it from the App Store, look in your MacOS X installation
DVD for an old version. Then update your Mac to update XCode.
- Download and install `MacPorts <http://www.macports.org/>`__, then - Download and install `MacPorts <http://www.macports.org/>`__, then
ensure its package list is up-to-date with ``sudo port selfupdate``. ensure its package list is up-to-date with ``sudo port selfupdate``.
......
...@@ -21,7 +21,8 @@ import re ...@@ -21,7 +21,8 @@ import re
import requests import requests
import shutil import shutil
import time import time
from subprocess import call, check_call, check_output, PIPE, STDOUT, CalledProcessError from subprocess import (call, check_call, check_output,
PIPE, STDOUT, CalledProcessError)
import sys import sys
import gh_api import gh_api
...@@ -30,12 +31,13 @@ basedir = os.path.join(os.path.expanduser("~"), ".theano_pr_tests") ...@@ -30,12 +31,13 @@ basedir = os.path.join(os.path.expanduser("~"), ".theano_pr_tests")
repodir = os.path.join(basedir, "Theano") repodir = os.path.join(basedir, "Theano")
ipy_repository = 'git://github.com/Theano/Theano.git' ipy_repository = 'git://github.com/Theano/Theano.git'
ipy_http_repository = 'http://github.com/Theano/Theano.git' ipy_http_repository = 'http://github.com/Theano/Theano.git'
gh_project="Theano/Theano" gh_project = "Theano/Theano"
supported_pythons = ['python2.6', 'python2.7', 'python3.1', 'python3.2'] supported_pythons = ['python2.6', 'python2.7', 'python3.1', 'python3.2']
supported_pythons = ['python2.7'] supported_pythons = ['python2.7']
unavailable_pythons = [] unavailable_pythons = []
def available_python_versions(): def available_python_versions():
"""Get the executable names of available versions of Python on the system. """Get the executable names of available versions of Python on the system.
""" """
...@@ -49,45 +51,50 @@ def available_python_versions(): ...@@ -49,45 +51,50 @@ def available_python_versions():
venvs = [] venvs = []
def setup(): def setup():
"""Prepare the repository and virtualenvs.""" """Prepare the repository and virtualenvs."""
global venvs global venvs
try: try:
os.mkdir(basedir) os.mkdir(basedir)
except OSError as e: except OSError as e:
if e.errno != errno.EEXIST: if e.errno != errno.EEXIST:
raise raise
os.chdir(basedir) os.chdir(basedir)
# Delete virtualenvs and recreate # Delete virtualenvs and recreate
for venv in glob('venv-*'): for venv in glob('venv-*'):
shutil.rmtree(venv) shutil.rmtree(venv)
for py in available_python_versions(): for py in available_python_versions():
check_call(['virtualenv', '-p', py, '--system-site-packages', 'venv-%s' % py]) check_call(['virtualenv', '-p', py,
'--system-site-packages', 'venv-%s' % py])
venvs.append((py, 'venv-%s' % py)) venvs.append((py, 'venv-%s' % py))
# Check out and update the repository # Check out and update the repository
if not os.path.exists('Theano'): if not os.path.exists('Theano'):
try : try:
check_call(['git', 'clone', ipy_repository]) check_call(['git', 'clone', ipy_repository])
except CalledProcessError : except CalledProcessError:
check_call(['git', 'clone', ipy_http_repository]) check_call(['git', 'clone', ipy_http_repository])
os.chdir(repodir) os.chdir(repodir)
check_call(['git', 'checkout', 'master']) check_call(['git', 'checkout', 'master'])
try : try:
check_call(['git', 'pull', ipy_repository, 'master']) check_call(['git', 'pull', ipy_repository, 'master'])
except CalledProcessError : except CalledProcessError:
check_call(['git', 'pull', ipy_http_repository, 'master']) check_call(['git', 'pull', ipy_http_repository, 'master'])
os.chdir(basedir) os.chdir(basedir)
missing_libs_re = re.compile(r"Tools and libraries NOT available at test time:\n" missing_libs_re = re.compile(r"Tools and libraries NOT available at test"
r"\s*(.*?)\n") r" time:\n\s*(.*?)\n")
def get_missing_libraries(log): def get_missing_libraries(log):
m = missing_libs_re.search(log) m = missing_libs_re.search(log)
if m: if m:
return m.group(1) return m.group(1)
def get_branch(repo, branch, owner, mergeable): def get_branch(repo, branch, owner, mergeable):
os.chdir(repodir) os.chdir(repodir)
if mergeable: if mergeable:
...@@ -103,6 +110,7 @@ def get_branch(repo, branch, owner, mergeable): ...@@ -103,6 +110,7 @@ def get_branch(repo, branch, owner, mergeable):
check_call(['git', 'checkout', 'FETCH_HEAD']) check_call(['git', 'checkout', 'FETCH_HEAD'])
os.chdir(basedir) os.chdir(basedir)
def run_tests(venv): def run_tests(venv):
py = os.path.join(basedir, venv, 'bin', 'python') py = os.path.join(basedir, venv, 'bin', 'python')
print(py) print(py)
...@@ -112,19 +120,19 @@ def run_tests(venv): ...@@ -112,19 +120,19 @@ def run_tests(venv):
shutil.rmtree('build') shutil.rmtree('build')
check_call([py, 'setup.py', 'install']) check_call([py, 'setup.py', 'install'])
os.chdir(basedir) os.chdir(basedir)
# Environment variables: # Environment variables:
orig_path = os.environ["PATH"] orig_path = os.environ["PATH"]
os.environ["PATH"] = os.path.join(basedir, venv, 'bin') + ':' + os.environ["PATH"] os.environ["PATH"] = os.path.join(basedir, venv,
'bin') + ':' + os.environ["PATH"]
os.environ.pop("PYTHONPATH", None) os.environ.pop("PYTHONPATH", None)
import pdb;pdb.set_trace()
iptest = os.path.join(basedir, venv, 'bin', 'theano-test') iptest = os.path.join(basedir, venv, 'bin', 'theano-test')
# if not os.path.exists(iptest): # if not os.path.exists(iptest):
# iptest = os.path.join(basedir, venv, 'bin', 'iptest3') # iptest = os.path.join(basedir, venv, 'bin', 'iptest3')
print("\nRunning tests, this typically takes a few minutes...") print("\nRunning tests, this typically takes a few minutes...")
try: try:
return True, check_output([iptest], stderr=STDOUT).decode('utf-8') return True, check_output([iptest], stderr=STDOUT).decode('utf-8')
except CalledProcessError as e: except CalledProcessError as e:
return False, e.output.decode('utf-8') return False, e.output.decode('utf-8')
...@@ -132,6 +140,7 @@ def run_tests(venv): ...@@ -132,6 +140,7 @@ def run_tests(venv):
# Restore $PATH # Restore $PATH
os.environ["PATH"] = orig_path os.environ["PATH"] = orig_path
def markdown_format(pr, results_urls, unavailable_pythons): def markdown_format(pr, results_urls, unavailable_pythons):
def format_result(py, passed, gist_url, missing_libraries): def format_result(py, passed, gist_url, missing_libraries):
s = "* %s: " % py s = "* %s: " % py
...@@ -142,7 +151,7 @@ def markdown_format(pr, results_urls, unavailable_pythons): ...@@ -142,7 +151,7 @@ def markdown_format(pr, results_urls, unavailable_pythons):
if missing_libraries: if missing_libraries:
s += " (libraries not available: " + missing_libraries + ")" s += " (libraries not available: " + missing_libraries + ")"
return s return s
if pr['mergeable']: if pr['mergeable']:
com = pr['head']['sha'][:7] + " merged into master" com = pr['head']['sha'][:7] + " merged into master"
else: else:
...@@ -152,19 +161,25 @@ def markdown_format(pr, results_urls, unavailable_pythons): ...@@ -152,19 +161,25 @@ def markdown_format(pr, results_urls, unavailable_pythons):
""] + \ ""] + \
[format_result(*r) for r in results_urls] + \ [format_result(*r) for r in results_urls] + \
["", ["",
"Not available for testing: " + ", ".join(unavailable_pythons)] "Not available for testing: " + ", ".join(unavailable_pythons)]
return "\n".join(lines) return "\n".join(lines)
def post_results_comment(pr, results, num, unavailable_pythons=unavailable_pythons):
def post_results_comment(pr, results, num,
unavailable_pythons=unavailable_pythons):
body = markdown_format(pr, results, unavailable_pythons) body = markdown_format(pr, results, unavailable_pythons)
gh_api.post_issue_comment(gh_project, num, body) gh_api.post_issue_comment(gh_project, num, body)
def print_results(pr, results_urls, unavailable_pythons=unavailable_pythons): def print_results(pr, results_urls, unavailable_pythons=unavailable_pythons):
print("\n") print("\n")
if pr['mergeable']: if pr['mergeable']:
print("**Test results for commit %s merged into master**" % pr['head']['sha'][:7]) print("**Test results for commit %s merged into master**" %
pr['head']['sha'][:7])
else: else:
print("**Test results for commit %s (can't merge cleanly)**" % pr['head']['sha'][:7]) print(
"**Test results for commit %s (can't merge cleanly)**" %
pr['head']['sha'][:7])
print("Platform:", sys.platform) print("Platform:", sys.platform)
for py, passed, gist_url, missing_libraries in results_urls: for py, passed, gist_url, missing_libraries in results_urls:
if passed: if passed:
...@@ -176,30 +191,34 @@ def print_results(pr, results_urls, unavailable_pythons=unavailable_pythons): ...@@ -176,30 +191,34 @@ def print_results(pr, results_urls, unavailable_pythons=unavailable_pythons):
print(" Libraries not available:", missing_libraries) print(" Libraries not available:", missing_libraries)
print("Not available for testing:", ", ".join(unavailable_pythons)) print("Not available for testing:", ", ".join(unavailable_pythons))
def dump_results(num, results, pr): def dump_results(num, results, pr):
with open(os.path.join(basedir, 'lastresults.pkl'), 'wb') as f: with open(os.path.join(basedir, 'lastresults.pkl'), 'wb') as f:
pickle.dump((num, results, pr, unavailable_pythons), f) pickle.dump((num, results, pr, unavailable_pythons), f)
def load_results(): def load_results():
with open(os.path.join(basedir, 'lastresults.pkl'), 'rb') as f: with open(os.path.join(basedir, 'lastresults.pkl'), 'rb') as f:
return pickle.load(f) return pickle.load(f)
def save_logs(results, pr): def save_logs(results, pr):
results_paths = [] results_paths = []
for py, passed, log, missing_libraries in results: for py, passed, log, missing_libraries in results:
if passed: if passed:
results_paths.append((py, passed, None, missing_libraries)) results_paths.append((py, passed, None, missing_libraries))
else: else:
result_locn = os.path.abspath(os.path.join('venv-%s' % py, result_locn = os.path.abspath(os.path.join('venv-%s' % py,
pr['head']['sha'][:7]+".log")) pr['head']['sha'][:7] + ".log"))
with io.open(result_locn, 'w', encoding='utf-8') as f: with io.open(result_locn, 'w', encoding='utf-8') as f:
f.write(log) f.write(log)
results_paths.append((py, False, result_locn, missing_libraries)) results_paths.append((py, False, result_locn, missing_libraries))
return results_paths return results_paths
def post_logs(results): def post_logs(results):
results_urls = [] results_urls = []
for py, passed, log, missing_libraries in results: for py, passed, log, missing_libraries in results:
...@@ -209,23 +228,24 @@ def post_logs(results): ...@@ -209,23 +228,24 @@ def post_logs(results):
result_locn = gh_api.post_gist(log, description='Theano test log', result_locn = gh_api.post_gist(log, description='Theano test log',
filename="results.log", auth=True) filename="results.log", auth=True)
results_urls.append((py, False, result_locn, missing_libraries)) results_urls.append((py, False, result_locn, missing_libraries))
return results_urls return results_urls
def test_pr(num, post_results=True): def test_pr(num, post_results=True):
# Get Github authorisation first, so that the user is prompted straight away # Get Github authorisation first, so that the user is prompted
# if their login is needed. # straight away if their login is needed.
if post_results: if post_results:
gh_api.get_auth_token() gh_api.get_auth_token()
setup() setup()
pr = gh_api.get_pull_request(gh_project, num) pr = gh_api.get_pull_request(gh_project, num)
get_branch(repo=pr['head']['repo']['clone_url'], get_branch(repo=pr['head']['repo']['clone_url'],
branch=pr['head']['ref'], branch=pr['head']['ref'],
owner=pr['head']['repo']['owner']['login'], owner=pr['head']['repo']['owner']['login'],
mergeable=pr['mergeable'], mergeable=pr['mergeable'],
) )
results = [] results = []
for py, venv in venvs: for py, venv in venvs:
tic = time.time() tic = time.time()
...@@ -237,27 +257,28 @@ def test_pr(num, post_results=True): ...@@ -237,27 +257,28 @@ def test_pr(num, post_results=True):
results.append((py, True, None, missing_libraries)) results.append((py, True, None, missing_libraries))
else: else:
results.append((py, False, log, missing_libraries)) results.append((py, False, log, missing_libraries))
dump_results(num, results, pr) dump_results(num, results, pr)
results_paths = save_logs(results, pr) results_paths = save_logs(results, pr)
print_results(pr, results_paths) print_results(pr, results_paths)
if post_results: if post_results:
results_urls = post_logs(results) results_urls = post_logs(results)
post_results_comment(pr, results_urls, num) post_results_comment(pr, results_urls, num)
print("(Posted to Github)") print("(Posted to Github)")
else: else:
post_script = os.path.join(os.path.dirname(sys.argv[0]), "post_pr_test.py") post_script = os.path.join(os.path.dirname(sys.argv[0]),
"post_pr_test.py")
print("To post the results to Github, run", post_script) print("To post the results to Github, run", post_script)
if __name__ == '__main__': if __name__ == '__main__':
import argparse import argparse
parser = argparse.ArgumentParser(description="Test an IPython pull request") parser = argparse.ArgumentParser(description="Test an Theano pull request")
parser.add_argument('-p', '--publish', action='store_true', parser.add_argument('-p', '--publish', action='store_true',
help="Publish the results to Github") help="Publish the results to Github")
parser.add_argument('number', type=int, help="The pull request number") parser.add_argument('number', type=int, help="The pull request number")
args = parser.parse_args() args = parser.parse_args()
test_pr(args.number, post_results=args.publish) test_pr(args.number, post_results=args.publish)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论