nedbat / django_coverage_plugin

A plugin for coverage.py to measure Django template execution
Apache License 2.0
197 stars 35 forks source link

Spurious missing lines reported if template has CRLF line endings #75

Open sparrowt opened 3 years ago

sparrowt commented 3 years ago

Summary

If the Django template HTML file has CRLF line endings (\r\n) then, depending on line and file lengths, some random lines may be reported as 'missing' even though they are covered. In my experience it happens more often on short lines later in the file, e.g. some closing HTML tags near the end.

Changing the line endings to LF-only (\n) in an affected file avoids the problem (reports 100%) - the bug is definitely because of the CRLF in the HTML template file, see 'Cause' section below. But first a minimal repro...

Repro

Cause

I believe the problem is caused by this plugin comparing character offsets (from start-of-file) into the template source string, loaded from 2 different bits of code which do it slightly differnetly:

  1. django_coverage_plugin.plugin.read_template_source specifies binary mode: open(filename, "rb") so this plugin is loading the HTML source including 2 characters \r\n at the end of each line if the file is CRLF
  2. django.template.loaders.filesystem.Loader.get_contents doesn't specify binary mode, so python 3 universal newlines behaviour results in the loaded HTML source having only 1 character \n at the end of each line, even though the file on disk has CRLF line endings

The comparison mismatch occurs because:

Therefore, depending on the length of each line, as it progresses down the file, offsets start to land on the wrong line as the off-by-one errors stack up.

Solution

I guess in this plugin we need to do one of these:

If (a) then it would be nice - if possible - to add a sanity check that the length of the string returned by read_template_source is the same as the length of the template that Django has loaded, if we can access that.

johnlarusic commented 2 years ago

Just adding that this exact same issue is happening to me. Going to see if I can force VSCode to just use the Unix-style line endings everywhere, but this fix would still be very much appreciated.

sronveaux commented 1 year ago

Hi,

Same problem here and very happy to see there is a workaround. Is there is a plan to make a fix for this one in an upcoming version?

Thanks for the wonderful job made on this plugin.