source: tests/pybin/tools.py @ 7cd8827

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexerpthread-emulationqualifiedEnum
Last change on this file since 7cd8827 was 0e0f128c, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

  • Property mode set to 100644
File size: 6.6 KB
RevLine 
[bacc36c]1from __future__ import print_function
2
[c07d724]3import __main__
4import argparse
[bacc36c]5import multiprocessing
[c07d724]6import os
7import re
[bacc36c]8import signal
[c07d724]9import stat
[bacc36c]10import sys
[f85bc15]11import fileinput
[c07d724]12
[bacc36c]13from pybin import settings
[c07d724]14from subprocess import Popen, PIPE, STDOUT
15
[bacc36c]16################################################################################
17#               shell helpers
18################################################################################
19
[c07d724]20# helper functions to run terminal commands
[bacc36c]21def sh(cmd, print2stdout = True, input = None):
22        # add input redirection if needed
23        if input and os.path.isfile(input):
24                cmd += " < %s" % input
25
26        # if this is a dry_run, only print the commands that would be ran
27        if settings.dry_run :
[c07d724]28                print("cmd: %s" % cmd)
29                return 0, None
[bacc36c]30
31        # otherwise create a pipe and run the desired command
32        else :
[c07d724]33                proc = Popen(cmd, stdout=None if print2stdout else PIPE, stderr=STDOUT, shell=True)
34                out, err = proc.communicate()
35                return proc.returncode, out
36
[f85bc15]37def is_ascii(fname):
38        if not os.path.isfile(fname):
39                return False
40
41        code, out = sh("file %s" % fname, print2stdout = False)
42        if code != 0:
43                return False
44
45        match = re.search(".*: (.*)", out)
46
47        if not match:
48                return False
49
[e1bdccb]50        return match.group(1).startswith("ASCII text")
[f85bc15]51
[c07d724]52# Remove 1 or more files silently
[bacc36c]53def rm( files ):
[28582b2]54        if isinstance( files, basestring ):
55                sh("rm -f %s > /dev/null 2>&1" % files )
56        else:
[c07d724]57                for file in files:
[bacc36c]58                        sh("rm -f %s > /dev/null 2>&1" % file )
[c07d724]59
[a95c117]60# Create 1 or more directory
61def mkdir( files ):
[28582b2]62        if isinstance( files, basestring ):
63                sh("mkdir -p %s" % os.path.dirname(files) )
64        else:
[a95c117]65                for file in files:
66                        sh("mkdir -p %s" % os.path.dirname(file) )
[28582b2]67
[a95c117]68
[c07d724]69def chdir( dest = __main__.__file__ ):
70        abspath = os.path.abspath(dest)
71        dname = os.path.dirname(abspath)
72        os.chdir(dname)
73
[bacc36c]74# diff two files
75def diff( lhs, rhs ):
76        # diff the output of the files
[bd56b07]77        diff_cmd = ("diff --ignore-all-space --text "
[bacc36c]78                                "--ignore-blank-lines "
79                                "--old-group-format='\t\tmissing lines :\n"
80                                "%%<' \\\n"
81                                "--new-group-format='\t\tnew lines :\n"
82                                "%%>' \\\n"
83                                "--unchanged-group-format='%%=' \\"
84                                "--changed-group-format='\t\texpected :\n"
85                                "%%<"
86                                "\t\tgot :\n"
87                                "%%>\n' \\\n"
88                                "--new-line-format='\t\t%%dn\t%%L' \\\n"
89                                "--old-line-format='\t\t%%dn\t%%L' \\\n"
90                                "--unchanged-line-format='' \\\n"
91                                "%s %s")
92
93        # fetch return code and error from the diff command
94        return sh(diff_cmd % (lhs, rhs), False)
95
96# call make
97def make(target, flags = '', redirects = '', error_file = None, silent = False):
98        test_param = """test="%s" """ % (error_file) if error_file else ''
99        cmd = ' '.join([
100                settings.make,
101                '-s' if silent else '',
102                test_param,
[575a6e5]103                settings.arch.flags,
[f3b9efc]104                settings.debug.flags,
[a5121bf]105                settings.install.flags,
[bacc36c]106                flags,
107                target,
108                redirects
109        ])
110        return sh(cmd)
111
[ed45af6]112def which(program):
113    import os
114    def is_exe(fpath):
115        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
116
117    fpath, fname = os.path.split(program)
118    if fpath:
119        if is_exe(program):
120            return program
121    else:
122        for path in os.environ["PATH"].split(os.pathsep):
123            exe_file = os.path.join(path, program)
124            if is_exe(exe_file):
125                return exe_file
126
127    return None
[bacc36c]128################################################################################
129#               file handling
130################################################################################
131
[c07d724]132# helper function to replace patterns in a file
133def file_replace(fname, pat, s_after):
[f85bc15]134        file = fileinput.FileInput(fname, inplace=True, backup='.bak')
135        for line in file:
136                print(line.replace(pat, s_after), end='')
137        file.close()
[c07d724]138
[0ad0c55]139# helper function to check if a files contains only a specific string
[c07d724]140def fileContainsOnly(file, text) :
141        with open(file) as f:
142                ff = f.read().strip()
143                result = ff == text.strip()
144
145                return result;
146
147# check whether or not a file is executable
148def fileIsExecutable(file) :
149        try :
150                fileinfo = os.stat(file)
151                return bool(fileinfo.st_mode & stat.S_IXUSR)
152        except Exception as inst:
153                print(type(inst))    # the exception instance
154                print(inst.args)     # arguments stored in .args
155                print(inst)
156                return False
157
[bacc36c]158# transform path to canonical form
159def canonicalPath(path):
[f85bc15]160        abspath = os.path.abspath(__main__.__file__)
161        dname = os.path.dirname(abspath)
162        return os.path.join(dname, os.path.normpath(path) )
[c07d724]163
[bacc36c]164# compare path even if form is different
165def pathCmp(lhs, rhs):
166        return canonicalPath( lhs ) == canonicalPath( rhs )
[c07d724]167
[bacc36c]168# walk all files in a path
169def pathWalk( op ):
170        def step(_, dirname, names):
171                for name in names:
172                        path = os.path.join(dirname, name)
173                        op( path )
174
175        # Start the walk
[56de5932]176        dname = settings.SRCDIR
[f85bc15]177        os.path.walk(dname, step, '')
[bacc36c]178
179################################################################################
180#               system
181################################################################################
182# count number of jobs to create
183def jobCount( options, tests ):
184        # check if the user already passed in a number of jobs for multi-threading
[d142ec5]185        if not options.jobs:
186                make_flags = os.environ.get('MAKEFLAGS')
187                force = bool(make_flags)
188                make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None
189                if make_jobs_fds :
190                        tokens = os.read(int(make_jobs_fds.group(2)), 1024)
191                        options.jobs = len(tokens)
192                        os.write(int(make_jobs_fds.group(3)), tokens)
193                else :
194                        options.jobs = multiprocessing.cpu_count()
[bacc36c]195        else :
[d142ec5]196                force = True
[bacc36c]197
198        # make sure we have a valid number of jobs that corresponds to user input
199        if options.jobs <= 0 :
200                print('ERROR: Invalid number of jobs', file=sys.stderr)
201                sys.exit(1)
202
[d142ec5]203        return min( options.jobs, len(tests) ), force
[bacc36c]204
205# setup a proper processor pool with correct signal handling
206def setupPool(jobs):
207        original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
208        pool = multiprocessing.Pool(jobs)
209        signal.signal(signal.SIGINT, original_sigint_handler)
210
211        return pool
212
213# handle signals in scope
214class SignalHandling():
215        def __enter__(self):
216                # enable signal handling
217                signal.signal(signal.SIGINT, signal.SIG_DFL)
218
219        def __exit__(self, type, value, traceback):
220                # disable signal handling
221                signal.signal(signal.SIGINT, signal.SIG_IGN)
222
223################################################################################
224#               misc
225################################################################################
226
227# check if arguments is yes or no
228def yes_no(string):
229        if string == "yes" :
230                return True
231        if string == "no" :
232                return False
233        raise argparse.ArgumentTypeError(msg)
[f3b9efc]234        return False
235
[ed45af6]236def fancy_print(text):
237        column = which('column')
238        if column:
239                cmd = "%s 2> /dev/null" % column
240                print(cmd)
241                proc = Popen(cmd, stdin=PIPE, stderr=None, shell=True)
242                proc.communicate(input=text)
243        else:
244                print(text)
Note: See TracBrowser for help on using the repository browser.