示例#1
0
    def run(self, i):
        try:
            s = "cmd=%s" % self.command
            if self.execute_cmd(
                    self.command, self.target_directory,
                    string_info=s) != 0:  # use uncolored string for cmake
                self.failed = True
        except:  # this fails, if the supplied command line is corrupted
            print(tools.red("Failed"))
            self.failed = True

        # if self fails, add error to number of errors
        if self.failed:
            self.nErrors += 1

        # move the std.out file
        old_std = os.path.join(self.target_directory, 'std.out')
        new_std = os.path.join(self.target_directory, 'std-%04d.out' % i)
        if os.path.exists(os.path.abspath(old_std)):  # check if file exists
            os.rename(old_std, new_std)

        # move the err.out file
        old_err = os.path.join(self.target_directory, 'std.err')
        new_err = os.path.join(self.target_directory, 'std-%04d.err' % i)
        if os.path.exists(os.path.abspath(old_err)):  # check if file exists
            os.rename(old_err, new_err)
示例#2
0
    def names(self):

        # read combinations in 'parameter.ini' for renaming the results
        combis, digits = getCombinations(self.parameter_file,
                                         CheckForMultipleKeys=True)

        # set "suffix"
        logging.getLogger('logger').debug("")
        logging.getLogger('logger').debug("")
        logging.getLogger('logger').debug(tools.yellow('=' * 132))
        logging.getLogger('logger').debug("Creating output name:")
        if not os.path.exists(self.names_file):
            print(
                tools.red("parameter_rename.ini file not found under: '%s'" %
                          self.names_file))
            exit(1)
        options_names, exclusions, noCrossCombinations = readKeyValueFile(
            self.names_file)
        suffix = ''
        for option in options_names:
            logging.getLogger('logger').debug("option.name=%s" %
                                              str(option.name))
            found, number = isKeyOf(combis[0], option.name)
            if found:
                logging.getLogger('logger').debug(
                    str(option.name) + " = " + tools.blue(str(found)) +
                    " (%s)" % combis[0][option.name])
                suffix += "_" + str(
                    option.values[0]) + "%s" % (combis[0][option.name])
            else:
                print(
                    str(option.name) + " = " + tools.red(str(found)) +
                    " (NOT FOUND!)")

        print("Name=[%s]" % tools.red(suffix))
        logging.getLogger('logger').debug(tools.yellow('=' * 132))
        logging.getLogger('logger').debug("")
        logging.getLogger('logger').debug("")

        self.suffix = suffix
        self.prefix = suffix[1:] + "_"
示例#3
0
    def __init__(self, cwd, command, names_file, names2_file, parameter_file):
        ExternalCommand.__init__(self)
        self.target_directory = cwd
        self.nErrors = 0
        self.command = command
        self.failed = False

        self.names_file = os.path.join(cwd, names_file)
        # check if file exists
        if not os.path.exists(self.names_file):
            print(
                tools.red("parameter_rename.ini file not found under: '%s'" %
                          self.names_file))
            exit(1)

        self.names2_file = os.path.join(cwd, names2_file)
        # check if file exists
        if not os.path.exists(self.names2_file):
            print(
                tools.red("parameter_change.ini file not found under: '%s'" %
                          self.names2_file))
            exit(1)

        self.parameter_file = os.path.join(cwd, parameter_file)
        # check if file exists
        if not os.path.exists(self.parameter_file):
            print(
                tools.red("parameter.ini file not found under: '%s'" %
                          self.parameter_file))
            exit(1)

        # display used files
        print("Using the following input files")
        print("parameter_rename.ini".ljust(25), " = [", self.names_file, "]")
        print("parameter_change.ini".ljust(25), " = [", self.names2_file, "]")
        print("parameter.ini       ".ljust(25), " = [", self.parameter_file,
              "]")
        print('=' * 132)
def readValueFromFile(filename, key):
    # Read the value of a single key from a file. Workflow:
    # 1.  Read file line by line:
    # 1.1   ignore exclusion (if line starts with 'exclude:')
    # 1.2   ignore noCrossCombination (if line starts with 'nocrosscombination:')
    # 1.3   get option and its values from line, if the key is the same as the key passed to the routine, break and return the matching value
    found = os.path.exists(filename)  # check if directory exists
    if not found:
        #raise getCombinationException(filename) # file not found
        raise Exception(
            tools.red("getCombination failed. file '%s' not found." %
                      filename))

    # 1. read options and exclusions from the file
    with open(filename) as f:
        for line in f.readlines():  # iterate over all lines of the file
            line = re.sub(
                r"\s+", "",
                line)  # remove all whitespaces ("\s" is the whitespac symbol)
            line = re.sub(
                r"\\s", " ", line
            )  # add new whitespaces for all occurrances of "\s" in the string ("\s" is NOT the whitespace symbol here)
            if line.startswith('!'):
                continue  # skip lines starting with a comment
            line = line.split('!')[0]  # remove comments

            # 1.1 read an exclusion
            if line.lower().startswith('exclude:'):
                continue  # ignore exclusion

            # 1.2 read a noCrossCombination
            if line.lower().startswith('nocrosscombination:'):
                continue  # ignore noCrossCombination

            # 1.3 read a option and its possible values
            if '=' in line:
                (currentKey, currentValue) = line.split('=',
                                                        1)  # split line at '='
                if key.lower() == currentKey.lower(
                ):  # check if the key matches the one passed to the routine
                    break  # if so, break from the for loop
                else:
                    continue  # better luck in the next line

    return currentValue
示例#5
0
def SummaryOfErrors(builds, args) :
    """
    General workflow:
    1. loop over all builds, examples, command_lines, runs and for every run set the output strings
       and get the maximal lengths of those strings
    2. print header
    3. loop over all builds
    3.1  print some information of the build
    3.2  within each build loop over all examples, command_lines, runs and for every run print some information:
    3.2.1  print an empty separation line if number of MPI threads changes
    3.2.2  print (only if changes) a line with all run parameters except the inner most, which is printed in 3.2.3
    3.2.3  print a line with following information:
             run.globalnumber, run.parameters[0] (the one not printed in 3.2.2), run.target_directory, MPI, run.walltime, run.result
    3.2.4  print the analyze results line by line
    """

    param_str_old    = ""
    str_MPI_old      = "-"
    restart_file_old = "-"

    # 1. loop over all runs and set output strings
    max_lens = collections.OrderedDict([ ("#run",4) , ("options",7) , ("path",4) , ("MPI",3), ("time",4) , ("Info",4) ])
    for build in builds :
        for example in build.examples :
            for command_line in example.command_lines :
                for run in command_line.runs :
                    run.output_strings = {}
                    run.output_strings['#run']    = str(run.globalnumber)
                    run.output_strings['options'] = ""
                    # Check number of variations in parameter list(run.digits.items())[0][1]
                    restart_file = command_line.parameters.get('restart_file', None)
                    run.restart_file_used = False
                    if list(run.digits.items())[0][1] > 0 :
                        run.output_strings['options'] += "%s=%s"%(list(run.parameters.items())[0]) # print parameter and value as [parameter]=[value]
                    elif restart_file : # if no parameter is varied, check if the restart file is used
                        run.restart_file_used = True
                        if restart_file != restart_file_old: # only display once
                            run.output_strings['options'] += "%s=%s"%('restart_file',restart_file) # print parameter and value as [parameter]=[value]
                            restart_file_old = restart_file

                    run.output_strings['path']    = os.path.relpath(run.target_directory,OutputDirectory.output_dir)
                    run.output_strings['MPI']     = command_line.parameters.get('MPI', '-')
                    run.output_strings['time']    = "%2.1f" % run.walltime
                    run.output_strings['Info']    = run.result
                    for key in run.output_strings.keys() :
                        max_lens[key] = max(max_lens[key], len(run.output_strings[key])) # set max column widths for summary table

    # 2. print header
    print(132*"=")
    print(" Summary of Errors"+"\n")
    spacing = 1
    for key, value in list(max_lens.items()) :
        print(key.ljust(value),spacing*' ', end=' ') # skip linebreak
    print("")

    # 3. loop over alls builds
    for build in builds :

        # 3.1 print cmake flags if no external binary was used for execution
        print('-'*132)
        if isinstance(build, check.Standalone) :
            print("Binary supplied externally under ",build.binary_path)
        elif isinstance(build, check.Build) :
            print("Build %d of %d (%s) compiled with in [%.2f sec]:" % (build.number, len(builds), build.result, build.walltime))
            print(" ".join(build.cmake_cmd_color))
            if build.return_code != 0 : break # stop output as soon as a failed build in encountered

        # 3.2 loop over all examples, command_lines and runs
        for example in build.examples :
            for command_line in example.command_lines :
                for run in command_line.runs :
                    # 3.2.1 print separation line only if MPI threads change
                    if run.output_strings["MPI"] != str_MPI_old :
                        print("")
                        str_MPI_old = run.output_strings["MPI"]
                    # 3.2.2 print the run parameters, except the inner most (this one is displayed in # 3.2.3)
                    paramsWithMultipleValues = [item for item in list(run.parameters.items())[1:] if run.digits[item[0]]>0 ]
                    param_str =", ".join(["%s=%s"%item for item in paramsWithMultipleValues]) # skip first index
                    restart_file = command_line.parameters.get('restart_file', None)
                    if not param_str_old.startswith(param_str) or len(param_str_old) == 0: # Only print when the parameter set changes
                        if restart_file and not run.restart_file_used and restart_file != restart_file_old: # Add restart file once
                            if len(param_str) > 0: param_str += ", "
                            param_str += "%s=%s" % ('restart_file',restart_file)
                            restart_file_old = restart_file
                        if len(param_str) > 0:
                            print("".ljust(max_lens["#run"]), spacing*' ', tools.yellow(param_str))

                    param_str_old = param_str

                    # 3.2.3 print all output_strings
                    for key,value in list(max_lens.items()) :
                        # Print options with .ljust
                        if key == "options" :
                            print(tools.yellow(run.output_strings[key].ljust(value)), end=' ') # skip linebreak
                        elif key == "MPI" and any([args.noMPI, args.noMPIautomatic]) :
                            print(tools.yellow("1"), end=' ') # skip linebreak
                        else :
                            print(run.output_strings[key].ljust(value), end=' ') # skip linebreak
                        print(spacing*' ', end=' ') # skip linebreak
                    print("")

                    # 3.2.4  print the analyze results line by line
                    for result in run.analyze_results :
                        print(tools.red(result).rjust(150))

                    # 3.2.5  print the external results line by line
                    for error in run.externals_errors :
                        print(tools.red(error).rjust(150))

                    # print an empty line after all errors were displayed
                    if len(run.analyze_results) > 0 or len(run.externals_errors):
                        print("")
示例#6
0
    def execute_cmd(self,
                    cmd,
                    target_directory,
                    name="std",
                    string_info=None,
                    environment=None,
                    displayOnFailure=True):
        """Execute an external program specified by 'cmd'. The working directory of this program is set to target_directory.
        Returns the return_code of the external program.

        cmd                                       : command given as list of strings (the command is split at every white space occurrence)
        target_directory                          : path to directory where the cmd command is to be executed
        name (optional, default="std")            : [name].std and [name].err files are created for storing the std and err output of the job
        string_info (optional, default=None)      : Print info regarding the command that is executed before execution
        environment (optional, default=None)      : run cmd command with environment variables as given by environment=os.environ (and possibly modified)
        displayOnFailure (optional, default=True) : Display error information if the code has failed to run: the last 15 lines of std.out and the last 15 lines of std.err
        """
        # Display string_info
        if string_info is not None:
            print(string_info)

        # check that only cmd arguments of type 'list' are supplied to this function
        if type(cmd) != type([]):
            print(
                tools.red("cmd must be of type 'list'\ncmd=") + str(cmd) +
                tools.red(" and type(cmd)="), type(cmd))
            exit(1)

        sys.stdout.flush(
        )  # flush output here, because the subprocess will force buffering until it is finished
        log = logging.getLogger('logger')

        workingDir = os.path.abspath(target_directory)
        log.debug(workingDir)
        log.debug(cmd)
        start = timer()
        (pipeOut_r, pipeOut_w) = os.pipe()
        (pipeErr_r, pipeErr_w) = os.pipe()

        self.stdout = []
        self.stderr = []

        bufOut = ""
        bufErr = ""

        if environment is None:
            self.process = subprocess.Popen(cmd, \
                                            stdout             = pipeOut_w, \
                                            stderr             = pipeErr_w, \
                                            universal_newlines = True, \
                                            cwd                = workingDir)
        else:
            self.process = subprocess.Popen(cmd, \
                                            stdout             = pipeOut_w, \
                                            stderr             = pipeErr_w, \
                                            universal_newlines = True, \
                                            cwd                = workingDir, \
                                            env                = environment)

        # .poll() is None means that the child is still running
        while self.process.poll() is None:
            # Loop as long as the select mechanism indicates there is data to be read from the buffer

            # 1.   std.out
            while len(select.select([pipeOut_r], [], [], 0)[0]) == 1:
                # Read up to a 1 KB chunk of data
                out_s = os.read(pipeOut_r, 1024)
                if not isinstance(out_s, str):
                    out_s = out_s.decode("utf-8", 'ignore')
                bufOut = bufOut + out_s
                tmp = bufOut.split('\n')
                for line in tmp[:-1]:
                    self.stdout.append(line + '\n')
                    log.debug(line)
                bufOut = tmp[-1]

            # 1.   err.out
            while len(select.select([pipeErr_r], [], [], 0)[0]) == 1:
                # Read up to a 1 KB chunk of data
                out_s = os.read(pipeErr_r, 1024)
                if not isinstance(out_s, str):
                    out_s = out_s.decode("utf-8", 'ignore')
                bufErr = bufErr + out_s
                tmp = bufErr.split('\n')
                for line in tmp[:-1]:
                    self.stderr.append(line + '\n')
                    log.info(line)
                bufErr = tmp[-1]

        os.close(pipeOut_w)
        os.close(pipeOut_r)
        os.close(pipeErr_w)
        os.close(pipeErr_r)

        self.return_code = self.process.returncode

        end = timer()
        self.walltime = end - start

        # write std.out and err.out to disk
        self.stdout_filename = os.path.join(target_directory, name + ".out")
        with open(self.stdout_filename, 'w') as f:
            for line in self.stdout:
                f.write(line)
        if self.return_code != 0:
            self.result = tools.red("Failed")
            self.stderr_filename = os.path.join(target_directory,
                                                name + ".err")
            with open(self.stderr_filename, 'w') as f:
                for line in self.stderr:
                    f.write(line)
        else:
            self.result = tools.blue("Successful")

        # Display result (Successful or Failed)
        if string_info is not None:
            # display result and wall time in previous line and shift the text by ncols columns to the right
            # Note that f-strings in print statements, e.g. print(f"...."), only work in python 3
            # print(f"\033[F\033[{ncols}G "+str(self.result)+" [%.2f sec]" % self.walltime)
            ncols = len(string_info) + 1
            print("\033[F\033[%sG " % ncols + str(self.result) +
                  " [%.2f sec]" % self.walltime)
        else:
            print(self.result + " [%.2f sec]" % self.walltime)

        # Display error information if the code has failed to run: the last 15 lines of std.out and the last 15 lines of std.err
        if log.getEffectiveLevel() != logging.DEBUG and displayOnFailure:
            if self.return_code != 0:
                for line in self.stdout[-15:]:
                    print(tools.red("%s" % line.strip()))
                for line in self.stderr[-15:]:
                    print(tools.red("%s" % line.strip()))

        return self.return_code
示例#7
0
import args_parser
import summary
"""
General workflow:
1.  get the command line arguments 'args' and all valid build combinations in the check directory from 'builds.ini'
2.  set the logger 'log' with the debug level from 'args' to determine the level of logging which displays output to the user
3.  perform the regression check by a) building executables
                                    b) running the code
                                    c) performing the defined analyzes
4.  display the summary table with information for each build, run and analysis step
5.  display if regression check was successful or not and return the corresponding error code
"""

print('')
print(
    tools.red('       oooooooo      ====================') +
    tools.yellow('=====================================') +
    tools.green('====================      oooooooo       '))
print(
    tools.red('    ooo   oo   ooo      _____    ______  ') +
    tools.yellow('  _____    _____   _____   ______    ') +
    tools.green(' ___         ___       ooo   oo   ooo    '))
print(
    tools.red('   oo     oo     oo    |  __ \  |  ____| ') +
    tools.yellow(' / ____|  / ____| |_   _| |  ____|   ') +
    tools.green('|__ \       / _ \     oo     oo     oo   '))
print(
    tools.red('  oo      oo      oo   | |__) | | |__    ') +
    tools.yellow('| |  __  | |  __    | |   | |__      ') +
    tools.green('   ) |     | | | |   oo      oo      oo  '))
print(
示例#8
0
import args_parser
"""
General workflow:
1.  FIX THIS: ------------------ get the command line arguments 'args' with path to ".gitlab-ci.yml" file
2.  FIX THIS: ------------------ set the logger 'log' with the debug level from 'args' to determine the level of logging which displays output to the user
3.  FIX THIS: ------------------ perform the regression check by a) building executables
                                    ------------------ b) running the code
                                    ------------------ c) performing the defined analyzes
4.  FIX THIS: ------------------ display the summary table with information for each build, run and analysis step
5.  FIX THIS: ------------------ display if regression check was successful or not and return the corresponding error code
"""

print('')
print(
    tools.red(
        '=============================================================================================================================='
    ))
print(
    tools.red(
        '         _____                    _____                    _____                    _____                    _____            '
    ))
print(
    tools.red(
        '         /\    \                  /\    \                  /\    \                  /\    \                  /\    \          '
    ))
print(
    tools.red(
        '        /::\    \                /::\    \                /::\    \                /::\    \                /::\    \         '
    ))
print(
    tools.red(
示例#9
0
args = parser.parse_args()

# set the logger 'log' with the debug level from 'args' to determine the level of logging which displays output to the user
tools.setup_logger(args.debug)
log = logging.getLogger('logger')

# check if file exists
if os.path.isdir(args.gitlab_ci):
    print(
        tools.yellow(
            "Supplied path is [%s]. Searching for '.gitlab-ci.yml' there." %
            args.gitlab_ci))
    args.gitlab_ci = os.path.join(args.gitlab_ci, '.gitlab-ci.yml')
if not os.path.exists(args.gitlab_ci):
    print(
        tools.red("gitlab-ci.yml file not found under: '%s'" % args.gitlab_ci))
    exit(1)

# display all command line arguments
print("Running with the following command line options")
for arg in args.__dict__:
    print("%s = [ %s ]" % (arg.ljust(15), getattr(args, arg)))
print('=' * 132)

# set the basedir (where the code is) and the reggiedir (where the reggie.py is)
basedir = os.path.abspath(os.path.dirname(args.gitlab_ci))
reggiedir = os.path.abspath(os.path.dirname(reggie_exe_path))

print(tools.blue("Using code under      [basedir]: " + str(basedir)))
print(tools.blue("Using reggie under  [reggiedir]: " + str(reggiedir)))
print(tools.blue("Running checks for [args.stage]: " + str(args.stage)))
示例#10
0
def getCombinations(filename,
                    CheckForMultipleKeys=False,
                    OverrideOptionKey=None,
                    OverrideOptionValue=None):
    # 1. get the key-value list from file
    # 1.1   get exclusion from line (if line starts with 'exclude:')
    # 1.2   get noCrossCombination from line (if line starts with 'nocrosscombination:')
    # 1.3   get option and it values from line ( option=value1 [,value2 [,value3 ...]] )
    options, exclusions, noCrossCombinations = readKeyValueFile(filename)

    # 1.4   Check if a options[].values (key in the dict) is to be overridden (removes all other occurrences too!)
    if OverrideOptionKey and OverrideOptionValue:
        print(
            tools.yellow("Setting all options for: %s=[%s]" %
                         (OverrideOptionKey, OverrideOptionValue)))

        # find the key/value pair in the options and replace the key/value + re-sort the list
        option_not_found = True
        for i in range(len(options)):
            if options[i].name == OverrideOptionKey:
                options[i].values = [OverrideOptionValue]
                option_not_found = False
        if option_not_found:
            raise Exception(
                tools.red(
                    "Trying to set %s = [%s], but %s was not found in the list."
                    % (OverrideOptionKey, OverrideOptionValue,
                       OverrideOptionKey)))

        options.sort(
            key=lambda option: len(option.values), reverse=True
        )  # sort list in order to have the most varying option at the beginning

    # 2.  Compute combinations:
    # 2.1   count total number of all combinations
    # 2.2   build only the valid combinations (that do NOT match any exclusion)
    # 2. compute combinations
    # 2.1 count total number of possible combinations without the exclusions
    combinations = []  # list of all VALID combinations

    NumOfCombinationsTotal = 1
    for option in options:
        option.base = NumOfCombinationsTotal  # save total  number of combinations of all options before this option
        NumOfCombinationsTotal = NumOfCombinationsTotal * len(option.values)

    logging.getLogger('logger').debug(
        "  Total number of combinations for '%s' = %d" %
        (filename, NumOfCombinationsTotal))

    if NumOfCombinationsTotal > 10000:
        raise Exception(
            tools.red(
                "more than 10000 combinations in parameter.ini are not allowed!"
            ))

    # 2.2 build all valid combinations (all that do not match any exclusion)
    for i in range(NumOfCombinationsTotal
                   ):  # iterate index 'i' over NumOfCombinationsTotal
        combination = collections.OrderedDict()
        digits = collections.OrderedDict()
        # build i-th combination by adding all options with their name and a certain value
        for option in options:
            # compute index in the list of values of the option
            # Explanation with Example:
            #   Assume you are reading the following file:
            #       opt1 = black,white
            #       opt2 = a,b,c
            #       opt3 = cat,dog,bird,snake
            #       opt4 = car,train
            #   Then you get 2*3*4*2 = 48 combinations in total. Let us imagine the options (opt1, opt2, ...)
            #   as digits in a crazy number system, where opt1 is the digit with the lowest value and
            #   opt4 with the highest value. Since we have different number of values for every digit, the base
            #   of each digit is not as in a standard number system like the decimal a series of powers 10^0, 10^1, 10^2, ...
            #   In our example we get the following bases for the options:
            #       base of opt1 = 1   (first digit has base 1 in every number system)
            #       base of opt2 = 2   (since opt1 has two   values, we get a 2 here)
            #       base of opt3 = 6   (since opt2 has three values and base=2, we get 2*3=6.  This is the number of combinations of opt1 and opt2)
            #       base of opt4 = 24  (since opt3 has foure values and base=6, we get 6*4=24. This is the number of combinations of opt1, opt2 and opt3)
            #   Luckily we already stored the base while counting the number of all combinations before.
            #   We now can compute the index in the list of values of an option (which is the value of the respective digit in our crazy number system)
            #   by dividing the index i (which is a number in our crazy number system) by the base and modulo the number of values of the option.
            j = (i / option.base) % len(option.values)
            digits[option.name] = int(j)

        for option in options:
            if CheckForMultipleKeys:
                # check if the same parameter name (e.g. 'BoundaryName') occurs more than once in the list and
                # move multiple occurances to a separate key/value where the value is a list of all occurances
                # this must be done, because dicts cannot have the same key name more than once (it is a dictionary)
                found, number = isKeyOf(combination, option.name)
                if found:
                    new_key = "MULTIPLE_KEY:" + option.name
                    logging.getLogger('logger').info(
                        tools.yellow(str(option.name)) +
                        " is already in list (found " + str(number) +
                        " times). Adding new key/value as " +
                        tools.yellow(new_key) + " with value=" +
                        option.values[digits[option.name]])
                    # create list for value in key/value pair for the new re-named option "MULTIPLE_KEY+X"
                    combination.setdefault(new_key, []).append(
                        option.values[digits[option.name]])
                    digits[new_key] = -100  # default value for special key
                else:
                    combination[option.name] = option.values[digits[
                        option.name]]
            else:
                combination[option.name] = option.values[digits[option.name]]

        # check if the combination is valid (does not match any exclusion)
        if anyIsSubset(exclusions, combination):
            continue  # if any exclusion matches the combination, the combination is invalid => cycle and do not add to list of valid combinations

        # check if option is marked with "noCrossCombinations", these are not to be permutated
        skip = False
        for noCrossCombination in noCrossCombinations:
            # Check if the parameter exists in the list
            if digits.get(noCrossCombination[0], None) is None:
                print(
                    tools.red(
                        "nocrosscombination [%s] not found in list of parameters given in [%s].\nOnly parameters that are read can be considered for nocrosscombination."
                        % (noCrossCombination[0], filename)))
                exit(1)

            # Check all noCrossCombinations and skip them is they already were added to the list
            if not all([
                    digits[key] == digits[noCrossCombination[0]]
                    for key in noCrossCombination
            ]):
                skip = True
                break

        # Don't add combination if it was marked skip=True
        if skip: continue

        # add valid combination
        combinations.append(combination)

    logging.getLogger('logger').debug("  Number of valid combinations = %d" %
                                      len(combinations))
    return combinations, digits
示例#11
0
def readKeyValueFile(filename):
    # General worflow:
    # 1.  Read file line by line:
    # 1.1   get exclusion from line (if line starts with 'exclude:')
    # 1.2   get noCrossCombination from line (if line starts with 'nocrosscombination:')
    # 1.3   get option and its values from line ( option=value1 [,value2 [,value3 ...]] )
    found = os.path.exists(filename)  # check if directory exists
    if not found:
        #raise getCombinationException(filename) # file not found
        raise Exception(
            tools.red("getCombination failed. file '%s' not found." %
                      filename))

    options = []  # list of all options
    exclusions = []  # list of all exclusions
    noCrossCombinations = []  # list of all noCrossCombinations

    # 1. read options and exclusions from the file
    with open(filename) as f:
        for line in f.readlines():  # iterate over all lines of the file
            line = re.sub(
                r"\s+", "",
                line)  # remove all whitespaces ("\s" is the whitespac symbol)
            line = re.sub(
                r"\\s", " ", line
            )  # add new whitespaces for all occurrances of "\s" in the string ("\s" is NOT the whitespace symbol here)
            if line.startswith('!'):
                continue  # skip lines starting with a comment
            line = line.split('!')[0]  # remove comments

            # 1.1 read an exclusion
            if line.lower().startswith('exclude:'):
                line = line.split(':', 1)[1]  # remove everything before ':''
                ex = {}  # new dictionary for the exclusion
                for key_value in splitValues(
                        line
                ):  # split at ',' (but not inside brackets) and iterate over key-value-pairs
                    (key, value) = key_value.split('=')
                    ex[key] = value  # save key and its value in the exclusion-dictionary

                exclusions.append(
                    ex)  # append exclusion to the list of all exclusions
                continue  # reading of exclusion finished -> go on with next line

            # 1.2 read a noCrossCombination
            if line.lower().startswith('nocrosscombination:'):
                line = line.split(':', 1)[1]  # remove everything before ':''
                noCrossCombination = line.split(
                    ',')  # list of keys, that should not be cross combined
                noCrossCombinations.append(
                    noCrossCombination
                )  # append noCrossCombination to the list of all noCrossCombinations
                continue  # reading of noCrossCombination finished -> go on with next line

            # 1.3 read a option and its possible values
            if '=' in line:
                (key, values) = line.split('=', 1)  # split line at '='
                option = Option(
                    key, splitValues(values)
                )  # generate new Option with a list of values (splitted at ',' but not inside brackets)
                options.append(option)  # append option to options list, where
                continue  # reading of option finished -> go on with next line

    options.sort(
        key=lambda option: len(option.values), reverse=True
    )  # sort list in order to have the most varying option at the beginning

    return options, exclusions, noCrossCombinations
示例#12
0
def getArgsAndBuilds():
    """get command line arguments and builds in check directory from 'builds.ini'"""
    parser = argparse.ArgumentParser(
        description=
        'DESCRIPTION:\nRegression checker for NRG codes.\nSupply the path to a /regressioncheck/checks/ directory within a repository containing a CMakeLists.txt file which can automatically be build using cmake. ',
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument('-c',
                        '--carryon',
                        action='store_true',
                        help='''Continue build/run process. 
      --carryon         : build non-existing binary-combinations and run all examples for thoses builds
      --carryon --run   : run all failed examples''')
    parser.add_argument(
        '-e',
        '--exe',
        help='Path to executable of code that should be tested.')
    parser.add_argument(
        '-m',
        '--MPIexe',
        help=
        'Path to mpirun executable. The correct MPI lib must be used, i.e. the one which which the executable (e.g. flexi) was compiled, e.g., /opt/openmpi/2.0.2/bin/mpirun.',
        default='mpirun')
    parser.add_argument('-d',
                        '--debug',
                        help='Debug level.',
                        type=int,
                        default=0)
    parser.add_argument(
        '-j',
        '--buildprocs',
        help='Number of processors used for compiling (make -j XXX).',
        type=int,
        default=0)
    parser.add_argument(
        '-b',
        '--basedir',
        help=
        'Path to basedir of code that should be tested (contains CMakeLists.txt).'
    )
    parser.add_argument(
        '-y',
        '--dummy',
        help=
        'Use dummy_basedir and dummy_checks for fast testing on dummy code.',
        action='store_true')
    parser.add_argument(
        '-r',
        '--run',
        help=
        'Run all binaries for all examples with all run-combinations for all existing binaries.',
        action='store_true')
    parser.add_argument(
        '-s',
        '--save',
        help=
        'Do not remove output directories buildsXXXX in output_dir after successful run.',
        action='store_true')
    parser.add_argument(
        '-t',
        '--compiletype',
        help=
        'Override all CMAKE_BUILD_TYPE settings by ignoring the value set in builds.ini (e.g. DEBUG or RELEASE).'
    )
    parser.add_argument('-a',
                        '--hlrs',
                        help='Run on with aprun (24-core hlrs system).',
                        action='store_true')
    parser.add_argument(
        '-z',
        '--rc',
        help=
        'Create/Replace reference files that are required for analysis. After running the program, the output files are stored in the check-/example-directory.',
        action='store_true',
        dest='referencescopy')
    parser.add_argument(
        '-f',
        '--fc',
        help=
        'Create/Replace required restart files (if defined in command_line.ini). After running the program, the output files are stored in the check-/example-directory.',
        action='store_true',
        dest='restartcopy')
    parser.add_argument(
        '-i',
        '--noMPI',
        help='Run program without "mpirun" (single thread execution).',
        action='store_true')
    parser.add_argument('check', help='Path to check-/example-directory.')

    #parser.set_defaults(carryon=False)
    #parser.set_defaults(dummy=False)
    #parser.set_defaults(run=False)
    #parser.set_defaults(save=False)
    #parser.set_defaults(hlrs=False)
    #parser.set_defaults(referencescopy=False)
    #parser.set_defaults(restartcopy=False)
    #parser.set_defaults(noMPI=False)

    # get reggie command line arguments
    args = parser.parse_args()

    # Set default values
    args.noMPIautomatic = False

    # Check OS
    if re.search('^linux', platform):
        hostname = socket.gethostname()
        print("platform: %s, hostname: %s" % (platform, hostname))
        if re.search('^mom[0-9]+$', hostname):
            print(
                tools.yellow(
                    'Automatic detection of hlrs system: Assuming aprun is used and setting args.hlrs = True'
                ))
            args.hlrs = True
        elif re.search('^eslogin[0-9]+$', hostname):
            if args.hlrs:
                raise Exception(
                    'Running with -a or --hlrs. Cannot run this program on a login node. Get interactive job and run on mom node!'
                )

    # setup basedir
    if args.dummy:
        # For testing reggie during reggie-developement:
        # Overwrite basedir and check directory with dummy directories.
        reggieDir = os.path.dirname(os.path.realpath(__file__))
        args.basedir = os.path.join(reggieDir, 'dummy_basedir')
        args.check = os.path.join(reggieDir, 'dummy_checks/test')
        print("Basedir directory switched to '%s'" % args.basedir)
        print("Check   directory switched to '%s'" % args.check)
    else:
        # For real reggie-execution:
        # Setup basedir (containing CMakeLists.txt) by searching upward from current working directory
        if args.basedir is None:
            args.basedir = os.getcwd()  # start with current working directory
        try:
            if args.exe is None:  # only get basedir if no executable is supplied
                args.basedir = tools.find_basedir(args.basedir)
        except Exception:
            print(
                tools.red(
                    "Basedir (containing 'CMakeLists.txt') not found!\nEither specify the basedir on the command line or execute reggie within a project with a 'CMakeLists.txt'."
                ))
            exit(1)

        if not os.path.exists(args.check):  # check if directory exists
            print(tools.red("Check directory not found: '%s'" % args.check))
            exit(1)

    # delete the building directory when [carryon = False] and [run = False] before getBuilds is called
    if not args.carryon and not args.run:
        tools.remove_folder(OutputDirectory.output_dir)

    # get builds from checks directory if no executable is supplied
    if args.exe is None:  # if not exe is supplied, get builds
        # read build combinations from checks/XX/builds.ini
        builds = check.getBuilds(args.basedir, args.check, args.compiletype)
    else:
        if not os.path.exists(args.exe):  # check if executable exists
            print(tools.red("No executable found under '%s'" % args.exe))
            exit(1)
        else:
            builds = [
                check.Standalone(args.exe, args.check)
            ]  # set builds list to contain only the supplied executable
            args.noMPIautomatic = check.StandaloneAutomaticMPIDetection(
                args.exe
            )  # Check possibly existing userblock.txt to find out if the executable was compiled with MPI=ON or MPI=OFF
            args.run = True  # set 'run-mode' do not compile the code
            args.basedir = None  # since code will not be compiled, the basedir is not required

    if args.run:
        print("args.run -> skip building")
        # in 'run-mode' remove all build from list of builds if their binaries do not exist (build.binary_exists() == False)
        builds = [build for build in builds if build.binary_exists()]

    if len(builds) == 0:
        print(
            tools.red("List of 'builds' is empty! Maybe switch off '--run'."))
        exit(1)

    # display all command line arguments
    print("Running with the following command line options")
    for arg in list(args.__dict__):
        print(arg.ljust(15) + " = [ " + str(getattr(args, arg)) + " ]")
    print('=' * 132)

    return args, builds