提交 a4a3b5eb authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Move call_nose.py to bin/theano-nose, add --batch

The --batch option makes it easier to call run_tests_in_batch
上级 85c052a7
...@@ -5,3 +5,4 @@ global-include *.sh ...@@ -5,3 +5,4 @@ global-include *.sh
recursive-include docs *.png *.gp recursive-include docs *.png *.gp
include distribute_setup.py include distribute_setup.py
include bin/theano-cache include bin/theano-cache
include bin/theano-nose
__authors__ = "Olivier Delalleau" #!/usr/bin/env python
__contact__ = "delallea@iro"
__authors__ = "Olivier Delalleau, Pascal Lamblin"
__contact__ = "delallea@iro"
""" """
This script should behave the same as the `nosetests` command. This script should behave the same as the `nosetests` command.
...@@ -8,16 +9,30 @@ This script should behave the same as the `nosetests` command. ...@@ -8,16 +9,30 @@ This script should behave the same as the `nosetests` command.
The reason for its existence is that on some systems, it may not be obvious to The reason for its existence is that on some systems, it may not be obvious to
find where nosetests is installed in order to run it in a different process. find where nosetests is installed in order to run it in a different process.
This script is called from `run_tests_in_batch.py`.
It is also used to load the KnownFailure plugin, in order to hide It is also used to load the KnownFailure plugin, in order to hide
KnownFailureTests error messages. KnownFailureTests error messages. Use --without-knownfailure to
disable that plugin.
If the --batch option is used, it will call `run_tests_in_batch.py`,
in order to run the tests by batches, not all at the same time.
`run_tests_in_batch.py` will in turn call back this script in another
process.
""" """
import logging
_logger = logging.getLogger('theano.bin.theano-nose')
_logger.setLevel(logging.WARN)
import nose import nose
import sys import sys
if __name__ == '__main__':
def main():
if '--batch' in sys.argv:
from theano.tests import run_tests_in_batch
sys.argv.remove('--batch')
return run_tests_in_batch.main()
addplugins = [] addplugins = []
# We include KnownFailure plugin by default, unless # We include KnownFailure plugin by default, unless
# it is disabled by the "--without-knownfailure" arg. # it is disabled by the "--without-knownfailure" arg.
...@@ -26,8 +41,14 @@ if __name__ == '__main__': ...@@ -26,8 +41,14 @@ if __name__ == '__main__':
from numpy.testing.noseclasses import KnownFailure from numpy.testing.noseclasses import KnownFailure
addplugins.append(KnownFailure()) addplugins.append(KnownFailure())
except ImportError: except ImportError:
pass _logger.warn(
'KnownFailure plugin from NumPy could not be imported')
else: else:
sys.argv.remove('--without-knownfailure') sys.argv.remove('--without-knownfailure')
sys.exit(nose.main(addplugins=addplugins)) return nose.main(addplugins=addplugins)
if __name__ == '__main__':
result = main()
sys.exit(result)
...@@ -141,7 +141,7 @@ def do_setup(): ...@@ -141,7 +141,7 @@ def do_setup():
'ChangeLog'], 'ChangeLog'],
'theano.misc': ['*.sh'] 'theano.misc': ['*.sh']
}, },
scripts=['bin/theano-cache'], scripts=['bin/theano-cache', 'bin/theano-nose'],
keywords=' '.join([ keywords=' '.join([
'theano', 'math', 'numerical', 'symbolic', 'blas', 'theano', 'math', 'numerical', 'symbolic', 'blas',
'numpy', 'gpu', 'autodiff', 'differentiation' 'numpy', 'gpu', 'autodiff', 'differentiation'
......
...@@ -36,7 +36,7 @@ import cPickle, os, subprocess, sys ...@@ -36,7 +36,7 @@ import cPickle, os, subprocess, sys
import theano import theano
def main(stdout=None, stderr=None, argv=None, call_nose=None): def main(stdout=None, stderr=None, argv=None, theano_nose=None):
""" """
Run tests with optional output redirection. Run tests with optional output redirection.
...@@ -46,8 +46,8 @@ def main(stdout=None, stderr=None, argv=None, call_nose=None): ...@@ -46,8 +46,8 @@ def main(stdout=None, stderr=None, argv=None, call_nose=None):
If argv is None, then we use arguments from sys.argv, otherwise we use the If argv is None, then we use arguments from sys.argv, otherwise we use the
provided arguments instead. provided arguments instead.
If call_nose is None, then we use the call_nose.py script found in If theano_nose is None, then we use the theano-nose script found in
theano/tests to call nosetests. Otherwise we call the provided script. Theano/bin to call nosetests. Otherwise we call the provided script.
""" """
if stdout is None: if stdout is None:
stdout = sys.stdout stdout = sys.stdout
...@@ -55,24 +55,25 @@ def main(stdout=None, stderr=None, argv=None, call_nose=None): ...@@ -55,24 +55,25 @@ def main(stdout=None, stderr=None, argv=None, call_nose=None):
stderr = sys.stderr stderr = sys.stderr
if argv is None: if argv is None:
argv = sys.argv argv = sys.argv
if call_nose is None: if theano_nose is None:
call_nose = os.path.join(theano.__path__[0], 'tests', 'call_nose.py') theano_nose = os.path.join(theano.__path__[0], '..', 'bin', 'theano-nose')
stdout_backup = sys.stdout stdout_backup = sys.stdout
stderr_backup = sys.stderr stderr_backup = sys.stderr
try: try:
sys.stdout = stdout sys.stdout = stdout
sys.stderr = stderr sys.stderr = stderr
run(stdout, stderr, argv, call_nose) run(stdout, stderr, argv, theano_nose)
finally: finally:
sys.stdout = stdout_backup sys.stdout = stdout_backup
sys.stderr = stderr_backup sys.stderr = stderr_backup
def run(stdout, stderr, argv, call_nose): def run(stdout, stderr, argv, theano_nose):
if len(argv) == 1: if len(argv) == 1:
tests_dir = theano.__path__[0] tests_dir = theano.__path__[0]
else: else:
assert len(argv) == 2 # tests_dir should be at the end of argv, there can be other arguments
tests_dir = argv[1] tests_dir = argv[-1]
other_args = argv[1:-1]
assert os.path.isdir(tests_dir) assert os.path.isdir(tests_dir)
os.chdir(tests_dir) os.chdir(tests_dir)
# It seems safer to fully regenerate the list of tests on each call. # It seems safer to fully regenerate the list of tests on each call.
...@@ -86,8 +87,10 @@ def run(stdout, stderr, argv, call_nose): ...@@ -86,8 +87,10 @@ def run(stdout, stderr, argv, call_nose):
stdout.flush() stdout.flush()
stderr.flush() stderr.flush()
dummy_in = open(os.devnull) dummy_in = open(os.devnull)
rval = subprocess.call(['python', call_nose, '--collect-only', '--with-id'], rval = subprocess.call(
stdin=dummy_in.fileno(), stdout=stdout.fileno(), [theano_nose, '--collect-only', '--with-id'] + other_args,
stdin=dummy_in.fileno(),
stdout=stdout.fileno(),
stderr=stderr.fileno()) stderr=stderr.fileno())
stdout.flush() stdout.flush()
stderr.flush() stderr.flush()
...@@ -111,8 +114,11 @@ def run(stdout, stderr, argv, call_nose): ...@@ -111,8 +114,11 @@ def run(stdout, stderr, argv, call_nose):
# We suppress all output because we want the user to focus only on the # We suppress all output because we want the user to focus only on the
# failed tests, which are re-run (with output) below. # failed tests, which are re-run (with output) below.
dummy_out = open(os.devnull, 'w') dummy_out = open(os.devnull, 'w')
rval = subprocess.call(['python', call_nose, '-q', '--with-id'] + rval = subprocess.call(
map(str, test_range), stdout=dummy_out.fileno(), ([theano_nose, '-q', '--with-id']
+ map(str, test_range)
+ other_args),
stdout=dummy_out.fileno(),
stderr=dummy_out.fileno(), stderr=dummy_out.fileno(),
stdin=dummy_in.fileno()) stdin=dummy_in.fileno())
# Recover failed test indices from the 'failed' field of the '.noseids' # Recover failed test indices from the 'failed' field of the '.noseids'
...@@ -132,8 +138,10 @@ def run(stdout, stderr, argv, call_nose): ...@@ -132,8 +138,10 @@ def run(stdout, stderr, argv, call_nose):
################################""" ################################"""
stdout.flush() stdout.flush()
stderr.flush() stderr.flush()
subprocess.call(['python', call_nose, '-v', '--with-id'] + failed, subprocess.call(
stdin=dummy_in.fileno(), stdout=stdout.fileno(), [theano_nose, '-v', '--with-id'] + failed + other_args,
stdin=dummy_in.fileno(),
stdout=stdout.fileno(),
stderr=stderr.fileno()) stderr=stderr.fileno())
stdout.flush() stdout.flush()
stderr.flush() stderr.flush()
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论