text: #!/usr/bin/env python
  """
  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
  find where nosetests is installed in order to run it in a different process.
  
  It is also used to load the KnownFailure plugin, in order to hide
  KnownFailureTests error messages. Use --without-knownfailure to
  disable that plugin.
  
  `run_tests_in_batch.py` will in turn call back this script in another process.
  """
  from __future__ import print_function
  
  __authors__ = "Olivier Delalleau, Pascal Lamblin, Eric Larsen"
  __contact__ = "delallea@iro"
  
  import logging
  _logger = logging.getLogger('theano.bin.theano-nose')
  
  import os
  import nose
  import textwrap
  import sys
  from nose.plugins import Plugin
  
  def main():
      # Handle the --theano arguments
      if "--theano" in sys.argv:
          i = sys.argv.index("--theano")
          import theano
          sys.argv[i] = theano.__path__[0]
  
      # Many Theano tests suppose device=cpu, so we need to raise an
      # error if device==gpu.
      # I don't know how to do this check only if we use theano-nose on
      # Theano tests.  So I make an try..except in case the script get
      # reused elsewhere.
      # We should not import theano before call nose.main()
      # As this cause import problem with nosetests.
      # Should we find a way to don't modify sys.path?
      if not os.path.exists('theano/__init__.py'):
          try:
              from theano import config
              if config.device != "cpu":
                  raise ValueError("Theano tests must be run with device=cpu."
                                   " This will also run GPU tests when possible.\n"
                                   " If you want GPU-related tests to run on a"
                                   " specific GPU device, and not the default one,"
                                   " you should use the init_gpu_device theano flag.")
          except ImportError:
              pass
  
      # Handle --batch[=n] arguments
      batch_args = [arg for arg in sys.argv if arg.startswith('--batch')]
      for arg in batch_args:
          sys.argv.remove(arg)
      batch_size = None
      if len(batch_args):
          if len(batch_args) > 1:
              _logger.warn(
                  'Multiple --batch arguments detected, using the last one '
                  'and ignoring the first ones.')
  
          batch_arg = batch_args[-1]
          elems = batch_arg.split('=', 1)
          if len(elems) == 2:
              batch_size = int(elems[1])
  
      # Handle the --debug-batch argument.
      display_batch_output = False
      if '--debug-batch' in sys.argv:
          if not batch_args:
              raise AssertionError(
                  'You can only use the --debug-batch argument with the '
                  '--batch[=n] option')
          while '--debug-batch' in sys.argv:
              sys.argv.remove('--debug-batch')
          sys.argv += ['--verbose', '--nocapture', '--detailed-errors']
          display_batch_output = True
  
      # Handle --time_prof arguments
      time_prof_args = [arg for arg in sys.argv if arg=='--time-profile']
      for arg in time_prof_args:
          sys.argv.remove(arg)
  
      # Time-profiling and batch modes
      if time_prof_args or batch_args:
          from theano.tests import run_tests_in_batch
          return run_tests_in_batch.main(
                  theano_nose=os.path.realpath(__file__),
                  batch_size=batch_size,
                  time_profile=bool(time_prof_args),
                  display_batch_output=display_batch_output)
  
      # Non-batch mode.
      addplugins = []
      # We include KnownFailure plugin by default, unless
      # it is disabled by the "--without-knownfailure" arg.
      if '--without-knownfailure' not in sys.argv:
          try:
              from numpy.testing.noseclasses import KnownFailure
              addplugins.append(KnownFailure())
          except ImportError:
              _logger.warn(
                  'KnownFailure plugin from NumPy could not be imported. '
                  'Use --without-knownfailure to disable this warning.')
      else:
          sys.argv.remove('--without-knownfailure')
  
      # When 'theano-nose' is called-back under the time-profile option, an
      # instance of the custom Nosetests plugin class 'DisabDocString' (see
      # below) is loaded. The latter ensures that the test name will not be
      # replaced in display by the first line of the documentation string.
      if '--disabdocstring' in sys.argv:
          addplugins.append(DisabDocString())
  
      try:
          if addplugins:
              ret = nose.main(addplugins=addplugins)
          else:
              ret = nose.main()
          return ret
      except TypeError as e:
          if "got an unexpected keyword argument 'addplugins'" in e.message:
              # This means nose is too old and does not support plugins
              _logger.warn(
                  'KnownFailure plugin from NumPy can\'t'
                  ' be used as nosetests is too old. '
                  'Use --without-knownfailure to disable this warning.')
              nose.main()
          else:
              raise
  
  
  def help():
      help_msg = """
          This script behaves mostly the same as the `nosetests` command.
  
          The main difference is that it loads automatically the
          KnownFailure plugin, in order to hide KnownFailureTests error
          messages. It also supports executing tests by batches.
  
          Local options:
  
              --help, -h: Displays this help.
  
              --batch[=n]:
                  If specified without option '--time-profile', do not run all
                  the tests in one run, but split the execution in batches of
                  `n` tests each. Default n is 100.
  
              --time-profile:
                  Each test will be run and timed separately and the results will
                  be deposited in the files 'timeprof_sort', 'timeprof_nosort'
                  and 'timeprof_rawlog' in the current directory. If the
                  '--batch[=n]' option is also specified, notification of the
                  progresses will be made to standard output after every group of
                  n tests. Otherwise, notification will occur after every group
                  of 100 tests.
  
                  The files 'timeprof_sort' and 'timeprof_nosort' both contain one
                  record for each test and comprise the following fields:
                  - test running-time
                  - nosetests sequential test number
                  - test name
                  - name of class to which test belongs (if any), otherwise full
                    information is contained in test name
                  - test outcome ('OK', 'SKIPPED TEST', 'FAILED TEST' or
                    'FAILED PARSING')
  
                  In 'timeprof_sort', test records are sorted according to
                  running-time whereas in 'timeprof_nosort' records are reported
                  according to sequential number. The former classification is the
                  main information source for time-profiling. Since tests belonging
                  to same or close classes and files have close sequential, the
                  latter may be used to identify duration patterns among the tests
                  numbers. A full log is also saved as 'timeprof_rawlog'.
  
              --without-knownfailure: Do not load the KnownFailure plugin.
  
              --theano: This parameter is replaced with the path to the theano
                        library. As theano-nose is a wrapper to nosetests, it
                        expects a path to the tests to run.
                        If you do not know where theano is installed, use this
                        option to have it inserted automatically.
  
              --debug-batch:
                  Use this parameter to run nosetests with options '--verbose',
                  '--nocapture' and '--detailed-errors' and show the output of
                  nosetests during batch execution.  This can be useful to debug
                  situations where re-running only the failed tests after batch
                  execution is not working properly. This option can only be used
                  in conjunction with the '--batch=[n]' argument.
  
          The other options will be passed to nosetests, see ``nosetests -h``.
          """
  
      print(textwrap.dedent(help_msg))
  
  
  class DisabDocString(Plugin):
  
      """
      When activated, a custom Nosetests plugin created through this class
      will preclude automatic replacement in display of the name of the test
      by the first line in its documentation string.
  
      Sources:
      http://nose.readthedocs.org/en/latest/developing.html
      http://nose.readthedocs.org/en/latest/further_reading.html
      http://www.siafoo.net/article/54
      https://github.com/nose-devs/nose/issues/294
      http://python-nose.googlecode.com/svn/trunk/nose/plugins/base.py
      Nat Williams:
      https://github.com/Merino/nose-description-fixer-plugin/commit/
          df94596f29c04fea8001713dd9b04bf3720aebf4
      """
  
      enabled = False # plugin disabled by default
      score = 2000  # high score ensures priority over other plugins
  
      def __init__(self):
          # 'super.__init__(self):' would have achieved exactly the same
          if self.name is None:
              self.name = self.__class__.__name__.lower()
          if self.enableOpt is None:
              self.enableOpt = ("enable_plugin_%s"
                                % self.name.replace('-', '_'))
  
      def options(self, parser, env):
          env_opt = 'NOSE_WITH_%s' % self.name.upper()
          # latter expression to be used if plugin called from the command line
          parser.add_option("--%s" % self.name,
                            # will be called with Nosetests 'main' or 'run'
                            # function's' argument '--disabdocstring'
                            action="store_true",
                            dest=self.enableOpt,
                            # the latter entails that the boolean self.enableOpt
                            # is set to 'True' when plugin is called through a
                            # function's argument
                            default=env.get(env_opt),
                            # entails that plugin will be enabled when command
                            # line trigger 'env_opt' will be activated
                            help="Enable plugin %s: %s [%s]" %
                            (self.__class__.__name__,
                             self.help(), env_opt))
  
      def configure(self, options, conf):
          self.conf = conf
          # plugin will be enabled when called through argument
          self.enabled = getattr(options, self.enableOpt)
  
      def describeTest(self, test):
          # 'describeTest' is also called when the test result in Nosetests calls
          # 'test.shortDescription()' and can thus be used to alter the display.
          return False
  
  if __name__ == '__main__':
      if '--help' in sys.argv or '-h' in sys.argv:
          help()
      else:
          result = main()
          sys.exit(result)
  