Modifying coverage reporting for python files is more difficult than need be.

Issue #646 closed
John Sirois created an issue

N.B.: Obsoletes

Currently the plugin api for providing a custom reporter is def file_reporter(filename) -> FileReporter. This API makes it hard to subclass PythonFileReporter since its constructor takes and optional coverage argument in addition to the morf to report on. In particular, the Coverage instance is not optional for the successful execution of fr.parser and fr.no_branch_lines. This can be worked around ~like so:

class MyFileReporter(PythonFileReporter):
  def __init__(self, morf, fancy_rel_filename, coverage=None):
    super(MyFileReporter, self).__init__(morf, coverage=coverage)
   self._fancy_rel_filename = fancy_rel_filename

  # What I want to customize:
  def relative_filename(self):
    return self._fancy_rel_filename

  # What I have to implement to workaround:
  def parser(self):
    """Lazily create a :class:`PythonParser`."""
    if self._parser is None:
      self._parser = PythonParser(
        exclude=None,  # Lost configurability here.
    return self._parser

  def no_branch_lines(self):
    no_branch = self.parser.lines_matching(
      join_regex(DEFAULT_PARTIAL[:]),  # Lost configurability here.
      join_regex(DEFAULT_PARTIAL_ALWAYS[:])  # Lost configurability here.
    return no_branch

The workaround is necessitated by the plugin lifecycle as it stands, where there is no access to the active Coverage instance FWICT. It looks like configuring plugins set up a bit of chicken/egg if Coverage passed itself into coverage_init; although, this would work in the example case since by the time MyFileReporter actually used the passed-in Coverage instance, it would be fulliy _init'ed. Perhaps the CoveragePlugin API could have def python_file_reporter(filename, coverage) -> PythonFileReporter method added or else there could be a PythonCoveragePlugin or CoveragePlugin2 API that amended the existing file_reporter API signature. ...Or, perhaps I'm missing something! That would be best.

I'm happy to whip up a patch if one is needed and any of these ideas or others would work.

Comments (7)

  1. Ned Batchelder repo owner

    @jsirois Thanks for the report, and for trying the plugins! Help me understand what you are trying to accomplish with your plugin: what's the larger problem you are trying to solve?

  2. John Sirois reporter

    Ah, looks like combine doesn't have any include/exclude filtering, so I think running 1 combine per source root won't do the trick. The 1st run will just map all symlink farm files to the 1st source root and then all remaining combines will no-op.

  3. Log in to comment