Ticket #9828: hudson_results.patch

File hudson_results.patch, 6.7 KB (added by robertwb, 12 years ago)
  • setup.py

    # HG changeset patch
    # User Robert Bradshaw <robertwb@math.washington.edu>
    # Date 1284703912 25200
    # Node ID 117000f776a9b985d9a3e3254d75fe1807918e8e
    # Parent  559d1f0400da45889dc0225d6ed372dd87d9fc95
    [mq]: hudson-results
    
    diff -r 559d1f0400da -r 117000f776a9 setup.py
    a b  
    3838else:
    3939    SAGE_VERSION = os.environ['SAGE_VERSION']
    4040
     41try:
     42    compile_result_dir = os.environ['XML_RESULTS']
     43    keep_going = True
     44except KeyError:
     45    compile_result_dir = None
     46    keep_going = False
     47
    4148SITE_PACKAGES = '%s/lib/python/site-packages/'%SAGE_LOCAL
    4249if not os.path.exists(SITE_PACKAGES):
    4350    SITE_PACKAGES = '%s/lib/python2.5/site-packages/'%SAGE_LOCAL
     
    110117ext_modules = ext_modules + sage.ext.gen_interpreters.modules
    111118
    112119
     120#########################################################
     121### Testing related stuff
     122#########################################################
     123
     124
     125class CompileRecorder(object):
     126
     127    def __init__(self, f):
     128        self._f = f
     129        self._obj = None
     130   
     131    def __get__(self, obj, type=None):
     132        # Act like a method...
     133        self._obj = obj
     134        return self
     135
     136    def __call__(self, *args):
     137        t = time.time()
     138        try:
     139            if self._obj:
     140                res = self._f(self._obj, *args)
     141            else:
     142                res = self._f(*args)
     143        except Exception, ex:
     144            print ex
     145            res = ex
     146        t = time.time() - t
     147       
     148        errors = failures = 0
     149        if self._f is compile_command0:
     150            name = "cythonize." + args[0][1].name
     151            failures = int(bool(res))
     152        else:
     153            name = "gcc." + args[0][1].name
     154            errors = int(bool(res))
     155        if errors or failures:
     156            type = "failure" if failures else "error"
     157            failure_item = """<%(type)s/>""" % locals()
     158        else:
     159            failure_item = ""
     160        output = open("%s/%s.xml" % (compile_result_dir, name), "w")
     161        output.write("""
     162            <?xml version="1.0" ?>
     163            <testsuite name="%(name)s" errors="%(errors)s" failures="%(failures)s" tests="1" time="%(t)s">
     164            <testcase classname="%(name)s" name="compile">
     165            %(failure_item)s
     166            </testcase>
     167            </testsuite>
     168        """.strip() % locals())
     169        output.close()
     170        return res
     171
     172if compile_result_dir:
     173    record_compile = CompileRecorder
     174else:
     175    record_compile = lambda x: x
     176
     177
    113178######################################################################
    114179# CODE for generating C/C++ code from Cython and doing dependency
    115180# checking, etc.  In theory distutils would run Cython, but I don't
     
    141206       
    142207    OUTPUT:
    143208        the given list of commands are all executed in serial
    144     """   
    145     for f,v in command_list:
    146         r = f(v)
    147         if r != 0:
    148             print "Error running command, failed with status %s."%r
    149             sys.exit(1)
     209    """
     210    process_command_results(f(v) for f,v in command_list)
    150211
    151212def run_command(cmd):
    152213    """
     
    188249    from multiprocessing import Pool
    189250    import twisted.persisted.styles #doing this import will allow instancemethods to be pickable
    190251    p = Pool(nthreads)
    191     for r in p.imap(apply_pair, command_list):
     252    process_command_results(p.imap(apply_pair, command_list))
     253
     254def process_command_results(result_values):
     255    error = None
     256    for r in result_values:
    192257        if r:
    193             print "Parallel build failed with status %s."%r
    194             sys.exit(1)
     258            print "Error running command, failed with status %s."%r
     259            if not keep_going:
     260                sys.exit(1)
     261            error = r
     262    if error:
     263        sys.exit(1)
    195264
    196265def number_of_threads():
    197266    """
     
    283352        # First, sanity-check the 'extensions' list
    284353        self.check_extensions_list(self.extensions)
    285354
    286         # We require MAKE to be set to decide how many cpus are
    287         # requested.
    288         if not os.environ.has_key('MAKE'):
    289             ncpus = 1
    290         else:
    291             MAKE = os.environ['MAKE']
    292             z = [w[2:] for w in MAKE.split() if w.startswith('-j')]
    293             if len(z) == 0:  # no command line option
    294                 ncpus = 1
    295             else:
    296                 # Determine number of cpus from command line argument.
    297                 # Also, use the OS to cap the number of cpus, in case
    298                 # user annoyingly makes a typo and asks to use 10000
    299                 # cpus at once.
    300                 try:
    301                     ncpus = int(z[0])
    302                     n = 2*number_of_threads()
    303                     if n:  # prevent dumb typos.
    304                         ncpus = min(ncpus, n)
    305                 except ValueError:
    306                     ncpus = 1
    307 
    308355        import time
    309356        t = time.time()
    310 
    311         if ncpus > 1:
    312 
    313             # First, decide *which* extensions need rebuilt at
    314             # all.
    315             extensions_to_compile = []
    316             for ext in self.extensions:
    317                 need_to_compile, p = self.prepare_extension(ext)
    318                 if need_to_compile:
    319                     extensions_to_compile.append(p)
    320 
    321             # If there were any extensions that needed to be
    322             # rebuilt, dispatch them using pyprocessing.
    323             if extensions_to_compile:
    324                from multiprocessing import Pool
    325                import twisted.persisted.styles #doing this import will allow instancemethods to be pickable
    326                p = Pool(min(ncpus, len(extensions_to_compile)))
    327                for r in p.imap(self.build_extension, extensions_to_compile):
    328                    pass
    329 
    330         else:
    331             for ext in self.extensions:
    332                 need_to_compile, p = self.prepare_extension(ext)
    333                 if need_to_compile:
    334                     self.build_extension(p)
     357       
     358        compile_commands = []
     359        for ext in self.extensions:
     360            need_to_compile, p = self.prepare_extension(ext)
     361            if need_to_compile:
     362                compile_commands.append((record_compile(self.build_extension), p))
     363       
     364        execute_list_of_commands(compile_commands)
    335365
    336366        print "Total time spent compiling C/C++ extensions: ", time.time() - t, "seconds."
    337367
     
    654684    else:
    655685        return f
    656686
    657 def compile_command(p):
     687def compile_command0(p):
    658688    """
    659689    Given a pair p = (f, m), with a .pyx file f which is a part the
    660690    module m, call Cython on f
     
    705735   
    706736    return r
    707737
     738# Can't pickle decorated functions.
     739compile_command = record_compile(compile_command0)
     740
     741
    708742def compile_command_list(ext_modules, deps):
    709743    """
    710744    Computes a list of commands needed to compile and link the