#!/usr/bin/env python

#*****************************************************************************
#       SAGE: Modular Forms Software, (c) William Stein, 2004
#
#       Copyright (C) 2004 William Stein <was@math.harvard.edu>
#
#  Distributed under the terms of the GNU General Public License (GPL)
#
#    This code is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    General Public License for more details.
#
#  The full text of the GPL is available at:
#
#                  http://www.gnu.org/licenses/
#*****************************************************************************

# doctest excludes any files whose absolute path contain these strings.
EXCLUDE = ["_setup", "__init__", "scripts", "_test", "__old", "debug", "deleted_code", ".pyc"]

import os, sys
from sage.misc.misc import cputime

os.environ["LD_LIBRARY_PATH"] = "/home/was/local/lib:"+\
                                os.environ["LD_LIBRARY_PATH"]

stop_on_errors = False
restrict = ""

if len(sys.argv) > 1:
    n = 1
    if sys.argv[n] == "-f":
        stop_on_errors = False
        n += 1
    if n < len(sys.argv):
        restrict = sys.argv[n]

    
def banner():
    print "\n\n\n\n"
    print "*"*80
    print "        Running Doctests!"
    print "*"*80
    
bad = []; skip = []; missing = []
def end_it():
    if len(bad) > 0:
        print "\n*************\n"
        print "The following modules had errors: " + ", ".join(bad)
        print "All other modules passed."
    else:
        print "All tests passed!!!"
    if len(skip) > 0:
        print "Skipped: " + ", ".join(skip)
    #if len(missing) > 0:
    #    print "Doctest code missing in " + ", ".join(missing)
    sys.exit(0)

def do_tests(dir, force=False, restrict=""):
    print "****"
    print "DIR = ", dir, "****"
    files = os.listdir(dir)
    files.sort()
    for F in files:
        do_skip = False
        ap = os.path.abspath(F)
        for s in EXCLUDE:
            if ap.find(s) != -1:
                do_skip = True
                continue
        if do_skip: continue

        test_file = "%s/__test_%s"%(dir,F)
        if F[-3:] == "pyx":
            test_file = test_file[:-1]
            
        if restrict=="" and not force and os.path.exists(test_file):
            if os.path.getctime(test_file) >= \
               os.path.getctime("%s/%s"%(dir,F)):
                do_skip = True
            
        if do_skip: continue
        
        if restrict != "" and F.find(restrict)==-1: continue

        if os.path.isdir(dir + '/' + F):
            if F != 'ext':
                do_tests(dir + "/" + F, force, restrict)
            continue
        if F[-3:] != ".py" and F[-4:] != ".pyx": continue
        X = open(dir + "/" + F,"r").readline()
        if X.find("nodoctest") == -1:
            s = "** Testing %s.%s "%(dir[2:].replace("/","."),F[:-3])
            file = "%s/%s"%(dir,F)
            #cmd = '/usr/bin/time -f "%%U" python %s'%file
            if F[-3:] == ".py":
                cmd = 'cd %s; doctest_py %s'%(dir, F)
            else:
                cmd = 'cd %s; doctest_pyx %s'%(dir,F)
            print s
            print cmd
            wt,rd,er = os.popen3(cmd)
            wt.close()
            r = rd.read()
            er = er.read()
            #print " "*70 + "(time: %s)"%(er.split()[3])
            if len(r) == 0:
                #print "** WARNING: Missing doctest in %s"%file
                missing.append(file)
            if r.find('failures') != -1 or len(er)>10:
                print "There were errors"
                print r
                print er
                bad.append(file)
                if stop_on_errors:
                    end_it()
        else:
            print "** Skipping %s"%F
            skip.append(F[:-3])

if __name__ ==  '__main__':
    import os, sys
    if len(sys.argv) > 1 and sys.argv[1] == '-f':
        force = True
        sys.argv.remove('-f')
    else:
        force = False
    banner()
    if len(sys.argv) > 1:
        restrict = sys.argv[1]
    else:
        restrict = ""
    if not force:
        print "Only testing modified files.  Do doctest -f to test all files."
    do_tests(".", force=force, restrict=restrict)
    end_it()
