Skip to content

Commit

Permalink
Handling of Windows (and legacy Mac) line endings (#47)
Browse files Browse the repository at this point in the history
Co-authored-by: Peter Cock <p.j.a.cock@googlemail.com>
  • Loading branch information
MarkusPiotrowski and peterjc authored Sep 2, 2020
1 parent db40a1a commit 1fc3c21
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 17 deletions.
14 changes: 9 additions & 5 deletions doc8/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,13 @@ def report_iter(self, line):
yield ("D003", "Tabulation used for indentation")


class CheckCarriageReturn(LineCheck):
class CheckCarriageReturn(ContentCheck):
REPORTS = frozenset(["D004"])

def report_iter(self, line):
if "\r" in line:
yield ("D004", "Found literal carriage return")
def report_iter(self, parsed_file):
for i, line in enumerate(parsed_file.lines):
if b"\r" in line:
yield (i + 1, "D004", "Found literal carriage return")


class CheckNewlineEndOfFile(ContentCheck):
Expand All @@ -75,7 +76,10 @@ def __init__(self, cfg):
super(CheckNewlineEndOfFile, self).__init__(cfg)

def report_iter(self, parsed_file):
if parsed_file.lines and not parsed_file.lines[-1].endswith(b"\n"):
if parsed_file.lines and not (
parsed_file.lines[-1].endswith(b"\n")
or parsed_file._lines[-1].endswith(b"\r")
):
yield (len(parsed_file.lines), "D005", "No newline at end of file")


Expand Down
11 changes: 7 additions & 4 deletions doc8/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,20 @@ def _read(self):
with self._read_lock:
if not self._has_read:
with open(self.filename, "rb") as fh:
self._lines = list(fh)
fh.seek(0)
self._raw_content = fh.read()
self._lines = self._raw_content.splitlines(True)
self._has_read = True

def lines_iter(self, remove_trailing_newline=True):
self._read()
for line in self._lines:
line = str(line, encoding=self.encoding)
if remove_trailing_newline and line.endswith("\n"):
line = line[0:-1]
if remove_trailing_newline:
# Cope with various OS new line conventions
if line.endswith("\n"):
line = line[:-1]
if line.endswith("\r"):
line = line[:-1]
yield line

@property
Expand Down
22 changes: 14 additions & 8 deletions doc8/tests/test_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,18 @@ def test_tabs(self):

class TestCarriageReturn(testtools.TestCase):
def test_cr(self):
lines = ["\tabc", "efg", "\r\n"]
check = checks.CheckCarriageReturn({})
errors = []
for line in lines:
errors.extend(check.report_iter(line))
self.assertEqual(1, len(errors))
(code, msg) = errors[0]
self.assertIn(code, check.REPORTS)
content = b"Windows line ending\r\nLegacy Mac line ending\r"
content += (b"a" * 79) + b"\r\n" + b"\r"
conf = {"max_line_length": 79}
with tempfile.NamedTemporaryFile() as fh:
fh.write(content)
fh.flush()
parsed_file = parser.ParsedFile(fh.name)
check = checks.CheckCarriageReturn(conf)
errors = list(check.report_iter(parsed_file))
self.assertEqual(4, len(errors))
(line, code, msg) = errors[0]
self.assertIn(code, check.REPORTS)


class TestLineLength(testtools.TestCase):
Expand Down Expand Up @@ -172,6 +176,8 @@ def test_newline(self):
(1, b"testing\ntesting"),
(0, b"testing\n"),
(0, b"testing\ntesting\n"),
(0, b"testing\r\n"),
(0, b"testing\r"),
]

for expected_errors, line in tests:
Expand Down

0 comments on commit 1fc3c21

Please sign in to comment.