diff --git a/path/__init__.py b/path/__init__.py index 33dd979..683846b 100644 --- a/path/__init__.py +++ b/path/__init__.py @@ -98,8 +98,9 @@ U_LINESEPS = LINESEPS + ['\u0085', '\u2028', '\u2029'] B_NEWLINE = re.compile('|'.join(LINESEPS).encode()) U_NEWLINE = re.compile('|'.join(U_LINESEPS)) -B_NL_END = re.compile(B_NEWLINE.pattern + b'$') -U_NL_END = re.compile(U_NEWLINE.pattern + '$') +# Group the alternation so $ anchors the whole newline, not only the last alt. +B_NL_END = re.compile(b'(?:' + B_NEWLINE.pattern + b')$') +U_NL_END = re.compile('(?:' + U_NEWLINE.pattern + ')$') _default_linesep = object() @@ -155,6 +156,8 @@ def _strip_newlines(lines: Iterable[str]) -> Iterator[str]: r""" >>> list(_strip_newlines(['Hello World\r\n', 'foo'])) ['Hello World', 'foo'] + >>> list(_strip_newlines(['Hello\nWorld\n', 'foo'])) + ['Hello\nWorld', 'foo'] """ return (U_NL_END.sub('', line) for line in lines) diff --git a/tests/test_path.py b/tests/test_path.py index b424bb6..1d74b22 100644 --- a/tests/test_path.py +++ b/tests/test_path.py @@ -318,6 +318,13 @@ def test_read_write(self, tmpdir): assert file.read_text(encoding='utf-8') == 'hello world' assert file.read_bytes() == b'hello world' + def test_write_lines_preserves_embedded_newlines(self, tmpdir): + file = path.Path(tmpdir) / 'filename' + file.write_lines(['Hello\nWorld', 'foo\r\nbar\n'], encoding='utf-8') + assert file.read_bytes() == ( + f'Hello\nWorld{os.linesep}foo\r\nbar{os.linesep}'.encode() + ) + class TestPerformance: @staticmethod