def run(self): out = "forcheck.log" p_info("\nRunning forcheck (stdout written to %s)" % out) with open(out, "w") as fout: # use pexpect.spawn instead of subprocess.Popen so we can get # real-time output from forcheck (Popen is subject to stdout being # buffered when redirected to PIPE). cmd = self.get_command() child = pexpect.spawn(cmd[0], args=cmd[1:], logfile=fout) self._store_prev = ("", "") while True: try: child.expect('\n') self._report_runtime_message(child.before) except pexpect.EOF: break child.close() self.rc = child.exitstatus try: p_info("\nDONE. (rc=%d, %s)" % (self.rc, EXIT_CODES[self.rc])) except KeyError: p_error("FAILED (rc=%d). See %s for details" % (self.rc, out))
def _locate_forcheck(self): """ Detect required environment variables (FCKDIR, FCKCNF). From those values, locate forchk binary and detects list of supported compiler emulators. sets self.cnfdir, self.forcheck_exe and self.supported_emulators """ p_info("\nLocating forcheck") if "FCKPWD" not in os.environ: raise CheckfortException("FCKPWD environment var not set") try: fdir = os.environ["FCKDIR"] except KeyError: raise CheckfortException("FCKDIR environment var not set") # locate exe candidates = map(lambda x: os.path.join(fdir, x, "forchk"), ("bin", ".")) try: found = (x for x in candidates if os.path.isfile(x)).next() except StopIteration: raise CheckfortException("Could not find 'forchk' binary") self.forcheck_exe = os.path.realpath(os.path.join(fdir, found)) # locate g95.cnf and assume all cnf files are in the same dir candidates = map(lambda x: os.path.join(fdir, x, "g95.cnf"), ("share/forcheck", ".")) try: found = (x for x in candidates if os.path.isfile(x)).next() except StopIteration: raise CheckfortException("Could not find '*.cnf' files") self.cnfdir = os.path.dirname(os.path.join(fdir, found)) # detect list of supported emulators self.supported_emulators = [x[:-4] for x in sieve(self.cnfdir, "*.cnf")] # guess version number by doing a trial run of forchk try: child = subprocess.Popen([self.forcheck_exe, "-batch"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) except: raise CheckfortException("Could not run " + self.forcheck_exe) # extract version string from output header first_line = child.communicate()[0].split("\n", 1)[0] last_col = first_line.rsplit(None, 1)[1] try: ver = re.match(r"V(\d+)\.(\d+)\.(\d+)", last_col).groups() self.forcheck_version = map(int, ver) except AttributeError: raise CheckfortException( self.forcheck_exe + " not producing expected output") p_info(" - install dir: %s" % fdir) p_info(" - executable: %s" % self.forcheck_exe) p_info(" - version: %s" % ".".join(str(v) for v in self.get_version())) # compare min version min_ver = tuple(int(x) for x in MIN_VESION.split(".")) if tuple(self.forcheck_version[:2]) < min_ver[:2]: p_error("Unsupported Forcheck version " "(version >=%s expected)." % MIN_VESION)
def main(): o, a = parse_options() cleaned = {} # store validated input options cleaned["outdir"] = o.outdir cleaned["pretend"] = bool(o.pretend) cleaned["extra_opts"] = shlex.split(o.extra_opts or "") # --compiler-emulation can only be checked once Forcheck is found. # Accept anything for now cleaned["emulation"] = o.emulation # Set log level if o.quiet or cleaned["pretend"]: set_silent_mode() elif o.verbose: set_verbose_mode() if o.debug: set_debug_mode() # Once output verbosity set, we can print the output header p_info("%s" % header) # check allowed standards if o.standard not in supported_standards: p_error("Unsupported fortran standard (%s). Options: %s" % (o.standard, ", ".join(supported_standards))) else: cleaned["standard"] = o.standard # deal with optional --free-form if o.free_form: if cleaned["standard"] == '77': p_warn("Fortran 77 does not support free format. Ignoring " "--free-form (-f) option.") o.free_form = False cleaned["free_format"] = bool(o.free_form) # check --ignore-err-codes (must be comma separated numeric codes) try: cleaned["ignore_list"] = list(set(int(x) for x in o.ignore.split(",") if x.strip())) except ValueError: p_error("Invalid value for --ignore-err-codes (-i). " "Expecting comma-separated list of numeric values") # read target files form positional args and --input-file option targets = a[:] # get targets from arguments if o.input_file: # get targets from file specified with --input-file try: targets.extend(InputFileReader(o.input_file).get_entries()) except IOError: p_error("Input file not readable: %s" % o.input_file) if not targets: p_error("No inputs provided.") # file extensions to search for if o.extensions: ext_list = [x.strip() for x in o.extensions.split(",")] else: ext_list = default_extensions # search and validate target files if any(os.path.isdir(x) for x in targets): p_info("Searching directories for files with the following " "extensions : %s" % " ".join("*.%s" % x for x in ext_list)) try: filelist = FileList(targets, ext_list) except CheckfortException, e: p_error(e)
if o.extensions: ext_list = [x.strip() for x in o.extensions.split(",")] else: ext_list = default_extensions # search and validate target files if any(os.path.isdir(x) for x in targets): p_info("Searching directories for files with the following " "extensions : %s" % " ".join("*.%s" % x for x in ext_list)) try: filelist = FileList(targets, ext_list) except CheckfortException, e: p_error(e) if not filelist.files: p_error("No relevant input files found.") cleaned["files"] = filelist.files # do actual work try: do_action(cleaned) except CheckfortException, e: p_error(e) def do_action(params): f = Forcheck(params["files"], fortran_standard=params["standard"], emulate_compiler=params["emulation"], free_format=params["free_format"], extra_opts=params["extra_opts"])