def report(self): """Execute CodePeer message reader and parses the output. Sets the exec_status property according to the success of the analysis: * ``GNAThub.EXEC_SUCCESS``: on successful execution and analysis * ``GNAThub.EXEC_FAILURE``: on any error """ self.info('clear existing results if any') GNAThub.Tool.clear_references(self.name) self.info('extract results with msg_reader') proc = GNAThub.Run(self.output_dir, self.__msg_reader_cmd_line(), out=self.csv_report, capture_stderr=False) if proc.status != 0: return GNAThub.EXEC_FAILURE self.info('analyse CSV report') self.tool = GNAThub.Tool(self.name) self.log.debug('parse report: %s', self.csv_report) if not os.path.isfile(self.csv_report): self.error('no report found') return GNAThub.EXEC_FAILURE with open(self.csv_report, 'rb') as report: # Compute the total number of lines for progress report (-1 because # the first line in irrelevant to the analysis). index, total = 0, len(report.readlines()) - 1 # Reset the read cursor to the first byte report.seek(0) # Create the tag "New" for new CodePeer messages added_tag = GNAThub.Property('codepeer:added', 'Added') removed_tag = GNAThub.Property('codepeer:removed', 'Removed') unchanged_tag = GNAThub.Property('codepeer:unchanged', 'Unchanged') try: # Parse the file and drop the first line (containing the # columns name). reader = csv.reader(report, quotechar='\"') # Drop the first line (containing the columns name) header = reader.next() self.log.debug('drop header line: %s', header) # Iterate over each relevant record for index, record in enumerate(reader, start=1): self.log.debug('parse record: %r', record) # Each row is a list of strings: # # File, Line, Column, Category, History, Has_Review, # Ranking, Kind, Message, Classification, CWE, Checks, # Primary_Checks, Subp, Timestamp, Approved By, Comment, # Message_Id (source, line, column, rule, history, has_review, severity, category, message, classification, cwe, checks, pchecks, subp, timestamp, app_by, comment, message_id) = record[:18] if not severity or severity == 'suppressed': # Some versions of codepeer report an empty severity # for suppressed messages: map this to 'info'. severity = 'info' rule_id = rule.lower() self.__add_message(source, line, column, rule_id, message, severity, message_id, [ added_tag if history == 'added' else (removed_tag if history == 'removed' else unchanged_tag) ]) if index % 100 == 1 or index == total: Console.progress(index, total, new_line=(index == total)) except csv.Error as why: self.log.exception('failed to parse CSV report') self.error('%s (%s:%d)' % (why, os.path.basename(self.csv_report), index)) return GNAThub.EXEC_FAILURE else: self.__do_bulk_insert() return GNAThub.EXEC_SUCCESS
def report(self): """Parse GNATcheck output file report. Returns according to the success of the analysis: * ``GNAThub.EXEC_SUCCESS``: on successful execution and analysis * ``GNAThub.EXEC_FAILURE``: on any error Identify two type of messages with different format: * basic message * message for package instantiation """ # Clear existing references only if not incremental run if not GNAThub.incremental(): self.info('clear existing results if any') GNAThub.Tool.clear_references(self.name) self.info('analyse report') self.tool = GNAThub.Tool(self.name) self.log.debug('parse report: %s', self.output) if not os.path.exists(self.output): self.error('no report found') return GNAThub.EXEC_FAILURE try: with open(self.output, 'r') as output: lines = output.readlines() total = len(lines) # Local variables used for exemptions handling exempted_violation = False hide_exempted = GNAThub.gnatcheck_hide_exempted() # Add the tag "exempted" for GNATcheck exempted violations exempt_tag = GNAThub.Property('gnatcheck:exempted', 'Exempted') prev_line = "" for index, line in enumerate(lines, start=1): self.log.debug('parse line: %s', line) # check if is a section title matchTitle = self._TITLE.match(line) if matchTitle: stitle = matchTitle.group('stitle') exempted_violation = stitle in ('Exempted', 'EXEMPTED') # filter messages if occurs in exempted violation section import_violation = not exempted_violation or ( exempted_violation and not hide_exempted) handle_exempted = exempted_violation and not hide_exempted if import_violation: if handle_exempted: match1 = self._MESSAGE.match(line) if match1: self.log.debug('matched: %s', str(match1.groups())) # Store this line in order to gather next line # justification if any if prev_line == "": prev_line = line else: # Second line is a new violation report match_prev = self._MESSAGE.match(prev_line) if match_prev: self.__parse_line_exempted( match_prev, [exempt_tag]) prev_line = line # self.__parse_line_exempted(match1, # [exempt_tag]) else: if prev_line != "": if len(line.strip()) != 0: # Handle justification for prev_line pmatch = self._MESSAGE.match(prev_line) if pmatch: self.__parse_line_exempted( pmatch, [exempt_tag], line.strip()) # Reset previous line value prev_line = "" else: match = self._MESSAGE.match(line) if match: self.log.debug('matched: %s', str(match.groups())) self.__parse_line(match) else: match2 = self._MESSAGE_INST.match(line) if match2: self.log.debug('matched 2: %s', str(match2.groups())) self.__parse_line_inst(match2) Console.progress(index, total, new_line=(index == total)) except IOError as why: self.log.exception('failed to parse report') self.error('%s (%s:%d)' % ( why, os.path.basename(self.output), total)) return GNAThub.EXEC_FAILURE else: self.__do_bulk_insert() return GNAThub.EXEC_SUCCESS
import GNAThub from support.asserts import ( assertEmpty, assertEqual, assertIsNotNone, assertNotEmpty, assertRaises ) base = GNAThub.Project.source_file('simple.adb') resource = GNAThub.Resource.get(base) assertIsNotNone(resource) tool = GNAThub.Tool('test-tool') assertIsNotNone(tool) rule = GNAThub.Rule('test-rule', 'test-rule-name', GNAThub.RULE_KIND, tool) assertIsNotNone(rule) prop0 = GNAThub.Property('test-prop-0', 'test-prop-name-0') assertIsNotNone(prop0) prop1 = GNAThub.Property('test-prop-1', 'test-prop-name-1') assertIsNotNone(prop1) msg0 = GNAThub.Message(rule, 'test message', properties=None) assertIsNotNone(msg0) assertEmpty(msg0.get_properties()) msg1 = GNAThub.Message(rule, 'test message', properties=[prop0, prop1]) assertIsNotNone(msg1) for msg in msg0, msg1: resource.add_message(msg) assertNotEmpty(msg1.get_properties())