@@ -539,7 +539,7 @@ def parse_cmd_output(cmd, stdouterr, ec, simple, log_all, log_ok, regexp):
539539 if use_regexp or regexp :
540540 res = parse_log_for_error (stdouterr , regexp , msg = "Command used: %s" % cmd )
541541 if len (res ) > 0 :
542- message = "Found %s errors in command output (output: %s)" % (len (res ), ", " .join ([r [0 ] for r in res ]))
542+ message = "Found %s errors in command output (output: %s)" % (len (res ), "\n \t " .join ([r [0 ] for r in res ]))
543543 if use_regexp :
544544 raise EasyBuildError (message )
545545 else :
@@ -589,3 +589,70 @@ def parse_log_for_error(txt, regExp=None, stdout=True, msg=None):
589589 (regExp , '\n ' .join ([x [0 ] for x in res ])))
590590
591591 return res
592+
593+
594+ def extract_errors_from_log (log_txt , reg_exps ):
595+ """
596+ Check provided string (command output) for messages matching specified regular expressions,
597+ and return 2-tuple with list of warnings and errors.
598+ :param log_txt: String containing the log, will be split into individual lines
599+ :param reg_exps: List of: regular expressions (as strings) to error on,
600+ or tuple of regular expression and action (any of [IGNORE, WARN, ERROR])
601+ :return (warnings, errors) as lists of lines containing a match
602+ """
603+ actions = (IGNORE , WARN , ERROR )
604+
605+ # promote single string value to list, since code below expects a list
606+ if isinstance (reg_exps , string_type ):
607+ reg_exps = [reg_exps ]
608+
609+ re_tuples = []
610+ for cur in reg_exps :
611+ try :
612+ if isinstance (cur , str ):
613+ # use ERROR as default action if only regexp pattern is specified
614+ reg_exp , action = cur , ERROR
615+ elif isinstance (cur , tuple ) and len (cur ) == 2 :
616+ reg_exp , action = cur
617+ else :
618+ raise TypeError ("Incorrect type of value, expected string or 2-tuple" )
619+
620+ if not isinstance (reg_exp , str ):
621+ raise TypeError ("Regular expressions must be passed as string, got %s" % type (reg_exp ))
622+ if action not in actions :
623+ raise TypeError ("action must be one of %s, got %s" % (actions , action ))
624+
625+ re_tuples .append ((re .compile (reg_exp ), action ))
626+ except Exception as err :
627+ raise EasyBuildError ("Invalid input: No regexp or tuple of regexp and action '%s': %s" , str (cur ), err )
628+
629+ warnings = []
630+ errors = []
631+ for line in log_txt .split ('\n ' ):
632+ for reg_exp , action in re_tuples :
633+ if reg_exp .search (line ):
634+ if action == ERROR :
635+ errors .append (line )
636+ elif action == WARN :
637+ warnings .append (line )
638+ break
639+ return warnings , errors
640+
641+
642+ def check_log_for_errors (log_txt , reg_exps ):
643+ """
644+ Check log_txt for messages matching regExps in order and do appropriate action
645+ :param log_txt: String containing the log, will be split into individual lines
646+ :param reg_exps: List of: regular expressions (as strings) to error on,
647+ or tuple of regular expression and action (any of [IGNORE, WARN, ERROR])
648+ """
649+ global errors_found_in_log
650+ warnings , errors = extract_errors_from_log (log_txt , reg_exps )
651+
652+ errors_found_in_log += len (warnings ) + len (errors )
653+ if warnings :
654+ _log .warning ("Found %s potential error(s) in command output (output: %s)" ,
655+ len (warnings ), "\n \t " .join (warnings ))
656+ if errors :
657+ raise EasyBuildError ("Found %s error(s) in command output (output: %s)" ,
658+ len (errors ), "\n \t " .join (errors ))
0 commit comments