def report_raw_stats( sect: Section, stats: LinterStats, old_stats: LinterStats | None, ) -> None: """Calculate percentage of code / doc / comment / empty.""" total_lines = stats.code_type_count["total"] sect.insert(0, Paragraph([Text(f"{total_lines} lines have been analyzed\n")])) lines = ["type", "number", "%", "previous", "difference"] for node_type in ("code", "docstring", "comment", "empty"): node_type = cast(Literal["code", "docstring", "comment", "empty"], node_type) total = stats.code_type_count[node_type] percent = float(total * 100) / total_lines if total_lines else None old = old_stats.code_type_count[node_type] if old_stats else None diff_str = diff_string(old, total) if old else None lines += [ node_type, str(total), f"{percent:.2f}" if percent is not None else "NC", str(old) if old else "NC", diff_str if diff_str else "NC", ] sect.append(Table(children=lines, cols=5, rheaders=1))
def _make_graph( filename: str, dep_info: Dict[str, Set[str]], sect: Section, gtype: str ): """generate a dependencies graph and add some information about it in the report's section """ outputfile = _dependencies_graph(filename, dep_info) sect.append(Paragraph((f"{gtype}imports graph has been written to {outputfile}",)))
def report_total_messages_stats( sect: Section, stats: LinterStats, previous_stats: LinterStats | None, ) -> None: """Make total errors / warnings report.""" lines = ["type", "number", "previous", "difference"] lines += checkers.table_lines_from_stats(stats, previous_stats, "message_types") sect.append(Table(children=lines, cols=4, rheaders=1))
def display_messages(self, layout): if self.msgs: # add stored messages to the layout msgs = self.header cols = len(self.header) msgs += self.msgs sect = Section('Messages') layout.append(sect) sect.append(Table(cols=cols, children=msgs, rheaders=1)) self.msgs = [] self._display(layout)
def make_reports(self, stats, old_stats): """render registered reports""" sect = Section("Report", "%s statements analysed." % (self.stats["statement"])) for checker in self.report_order(): for reportid, r_title, r_cb in self._reports[checker]: if not self.report_is_enabled(reportid): continue report_sect = Section(r_title) try: r_cb(report_sect, stats, old_stats) except EmptyReportError: continue report_sect.report_id = reportid sect.append(report_sect) return sect
def set_output(self, output=None): """set output stream messages buffered for old output is processed first""" if self.out and self.msgs: self._display(Section()) BaseReporter.set_output(self, output)
def test_html_reporter_msg_template(self): expected = ''' <html> <body> <div> <div> <h2>Messages</h2> <table> <tr class="header"> <th>category</th> <th>msg_id</th> </tr> <tr class="even"> <td>warning</td> <td>W0332</td> </tr> </table> </div> </div> </body> </html>'''.strip().splitlines() output = six.StringIO() linter = PyLinter(reporter=HTMLReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.set_option('msg-template', '{category}{msg_id}') linter.open() linter.set_current_module('0123') linter.add_message('lowercase-l-suffix', line=1) linter.reporter.display_results(Section()) self.assertEqual(output.getvalue().splitlines(), expected)
def report_messages_stats( sect: Section, stats: LinterStats, _: LinterStats | None, ) -> None: """Make messages type report.""" by_msg_stats = stats.by_msg in_order = sorted( (value, msg_id) for msg_id, value in by_msg_stats.items() if not msg_id.startswith("I") ) in_order.reverse() lines = ["message id", "occurrences"] for value, msg_id in in_order: lines += [msg_id, str(value)] sect.append(Table(children=lines, cols=2, rheaders=1))
def _display(self, layout): """launch layouts display overridden from BaseReporter to add insert the messages section (in add_message, message is not displayed, just collected so it can be displayed in an html table) """ if self.msgs: # add stored messages to the layout msgs = self.header cols = len(self.header) msgs += self.msgs sect = Section('Messages') layout.append(sect) sect.append(Table(cols=cols, children=msgs, rheaders=1)) self.msgs = [] HTMLWriter().format(layout, self.out)
def report_by_type_stats( sect: reporter_nodes.Section, stats: LinterStats, old_stats: LinterStats | None, ) -> None: """Make a report of. * percentage of different types documented * percentage of different types with a bad name """ # percentage of different types documented and/or with a bad name nice_stats: dict[str, dict[str, str]] = {} for node_type in ("module", "class", "method", "function"): node_type = cast(Literal["function", "class", "method", "module"], node_type) total = stats.get_node_count(node_type) nice_stats[node_type] = {} if total != 0: undocumented_node = stats.get_undocumented(node_type) documented = total - undocumented_node percent = (documented * 100.0) / total nice_stats[node_type]["percent_documented"] = f"{percent:.2f}" badname_node = stats.get_bad_names(node_type) percent = (badname_node * 100.0) / total nice_stats[node_type]["percent_badname"] = f"{percent:.2f}" lines = [ "type", "number", "old number", "difference", "%documented", "%badname" ] for node_type in ("module", "class", "method", "function"): node_type = cast(Literal["function", "class", "method", "module"], node_type) new = stats.get_node_count(node_type) old = old_stats.get_node_count(node_type) if old_stats else None diff_str = lint_utils.diff_string(old, new) if old else None lines += [ node_type, str(new), str(old) if old else "NC", diff_str if diff_str else "NC", nice_stats[node_type].get("percent_documented", "0"), nice_stats[node_type].get("percent_badname", "0"), ] sect.append(reporter_nodes.Table(children=lines, cols=6, rheaders=1))
def report_messages_by_module_stats( sect: Section, stats: LinterStats, _: LinterStats | None, ) -> None: """Make errors / warnings by modules report.""" module_stats = stats.by_module if len(module_stats) == 1: # don't print this report when we are analysing a single module raise exceptions.EmptyReportError() by_mod: defaultdict[str, dict[str, int | float]] = collections.defaultdict(dict) for m_type in ("fatal", "error", "warning", "refactor", "convention"): total = stats.get_global_message_count(m_type) for module in module_stats.keys(): mod_total = stats.get_module_message_count(module, m_type) percent = 0 if total == 0 else float(mod_total * 100) / total by_mod[module][m_type] = percent sorted_result = [] for module, mod_info in by_mod.items(): sorted_result.append( ( mod_info["error"], mod_info["warning"], mod_info["refactor"], mod_info["convention"], module, ) ) sorted_result.sort() sorted_result.reverse() lines = ["module", "error", "warning", "refactor", "convention"] for line in sorted_result: # Don't report clean modules. if all(entry == 0 for entry in line[:-1]): continue lines.append(line[-1]) for val in line[:-1]: lines.append(f"{val:.2f}") if len(lines) == 5: raise exceptions.EmptyReportError() sect.append(Table(children=lines, cols=5, rheaders=1))
def test_display_results_is_renamed(self): class CustomReporter(TextReporter): def _display(self, layout): return None reporter = CustomReporter() if __pkginfo__.numversion >= (2, 0): with self.assertRaises(AttributeError): reporter.display_results else: with testutils.catch_warnings() as cm: reporter.display_results(Section()) self.assertEqual(len(cm), 1) self.assertIsInstance(cm[0].message, DeprecationWarning)
def test_html_reporter_type(self): # Integration test for issue #263 # https://bitbucket.org/logilab/pylint/issue/263/html-report-type-problems expected = '''<html> <body> <div> <div> <h2>Messages</h2> <table> <tr class="header"> <th>type</th> <th>module</th> <th>object</th> <th>line</th> <th>col_offset</th> <th>message</th> </tr> <tr class="even"> <td>convention</td> <td>0123</td> <td> </td> <td>1</td> <td>0</td> <td>Exactly one space required before comparison a< 5: print "zero"</td> </tr> </table> </div> </div> </body> </html> ''' output = six.StringIO() with testutils.catch_warnings(): linter = PyLinter(reporter=HTMLReporter()) checkers.initialize(linter) linter.config.persistent = 0 linter.reporter.set_output(output) linter.open() linter.set_current_module('0123') linter.add_message('bad-whitespace', line=1, args=('Exactly one', 'required', 'before', 'comparison', 'a< 5: print "zero"')) linter.reporter.display_reports(Section()) self.assertMultiLineEqual(output.getvalue(), expected)
def make_reports(self, stats, old_stats): """render registered reports""" sect = Section('Report', '%s statements analysed.' % (self.stats['statement'])) for checker in self.report_order(): for reportid, r_title, r_cb in self._reports[checker]: if not self.report_is_enabled(reportid): continue report_sect = Section(r_title) try: r_cb(report_sect, stats, old_stats) except EmptyReport: continue report_sect.report_id = reportid sect.append(report_sect) return sect
def make_reports( # type: ignore[misc] # ReportsHandlerMixIn is always mixed with PyLinter self: "PyLinter", stats: LinterStats, old_stats: Optional[LinterStats], ) -> Section: """render registered reports""" sect = Section("Report", f"{self.stats.statement} statements analysed.") for checker in self.report_order(): for reportid, r_title, r_cb in self._reports[checker]: if not self.report_is_enabled(reportid): continue report_sect = Section(r_title) try: r_cb(report_sect, stats, old_stats) except EmptyReportError: continue report_sect.report_id = reportid sect.append(report_sect) return sect