`# pragma: no cover` but specific to particular Python version

Issue #370 wontfix
Tim Tisdall created an issue

This is related to: https://github.com/Pylons/colander/issues/226

            functools.update_wrapper(self, wrapped)
        except AttributeError: #non-function
            self.__doc__ = getattr(wrapped, '__doc__', None)

There seems to be cases where you need to write code to cover cases in certain versions of Python that are then inaccessible in other versions. In the above example there's code to handle an exception that occurs in py2, but never happens in py3 (in this situation). It'd be nice to selectively exclude coverage for only certain versions of Python but include it in the versions it's necessary for.

Comments (10)

  1. Ned Batchelder repo owner

    You already have all the control you need to create a system like this yourself. The pragma is simply the default for the [report]exclude_lines option in your .coveragerc file. If you like, you can create two config files, one for py2 and another for py3, and specify different pragma syntaxes in each.

  2. Barry Warsaw

    @ned I'd like to make a case for reopening this issue. This is somewhat related to #563 and #172, but I'll give a use case for why multiple coverage.ini files gets inconvenient.

    In aiosmtpd, as it turns out we need 6 (!) different coverage.ini files to handle all of Python 3.4, 3.5, and 3.6 on both *nix and Windows. Now, the 3.5 and 3.6 versions are identical but because of the way we integrate this with our tox.ini, and the fact that 3.4 has to be special, we end up with one coverage file per Python version per OS. Even if we could combine 3.5 and 3.6, we'd still end up with four coverage.ini files. I can probably hide the clutter inside a subdirectory, but I'd still love to have just one coverage.ini file (and then be able to remove the extra cruft from my tox.ini).

    Imagining how this might look:

    # ...
    # ...
    exclude_lines =
        pragma: nocover
    exclude_lines =
        pragma: nossl
    exclude_lines =
        pragma: nomswin

    Thus for Python 3.5 and 3.6 on nix, we'd just exclude nocover lines. For 3.4 we'd add nossl excludes, and for mswin we'd add* nomswin lines.

    Our tox.ini bit looks like:

    rcfile = {toxinidir}/{env:INTERP:py35}{env:PLATFORM:}-coverage.ini
    rc = --rcfile={[coverage]rcfile}

    Is there's a better way to do this with the existing features that I'm missing?

  3. Ned Batchelder repo owner

    I would still like to keep coverage.py out of the business of knowing what all of the variables might be.

    How about this? You already have environment variables INTERP and PLATFORM. Your .coveragerc could have:

    exclude_lines = 
        pragma: nocover
        pragma: no${INTERP}
        pragma: no${PLATFORM}

    You'd want to define PLATFORM for non-windows. This doesn't deal with py34 implying nossl. Either change the pragma to nopy34, or add another environment variable MISSING_FEATURE1 (ick?).

  4. Tim Tisdall reporter

    It's been a while since I touched this stuff, but is it possible to stack the comments such as # pragma: nopy34 # pragma: nopy35? That seems like a necessary feature if you tried using pragma: no${INTERP}.

  5. Tim Tisdall reporter

    @warsaw - I was asking if that method currently worked, I wasn't endorsing it as an ideal format. I don't recall if the comment is required to be at the end of a line or just somewhere in the line.

  6. Ned Batchelder repo owner

    There's no requirement that it be a comment at all. The values of exclude_lines are regexes that are searched in the source lines. I often put def __repr__ in my list. So you could use a regex like pragma:.*no${INTERP} and then your comments like "# pragma: nopy34, nopy35" would work just fine.

  7. Tim Tisdall reporter

    Ah.. I thought they were straight string matches, not regex. So, I guess what I mentioned would work, but your regex example would be much cleaner.

    However, back to the original posted issue, I think an environment variable or separate coverage.ini would be the best way to handle things since every new version of py3 would require searching through all source code and adding a new tag. I guess it all depends on the size of the project and how many tags there are. It would be nice to have a builtin variable like ${INTERP} that just had the major revision (ie py2 vs py3), but it'd quickly come back to an issue like Barry's where you need something more.

  8. Barry Warsaw

    @ned Thanks for the suggestions. I was able to collapse things down to a single coverage.ini file, although now I have suggestions for improving tox (not your problem of course :). The $INTERP and $PLATFORM envars come from our .travis.yml and .appveyor.yml files but of course those aren't used when running the tests on the command line, but now I have to set them in tox.ini. That's probably better anyway.

  9. Log in to comment