Skip to content

Commit

Permalink
Respect existing line endings (#122)
Browse files Browse the repository at this point in the history
Fixes #104
  • Loading branch information
kurtmckee authored Jan 16, 2023
1 parent 8e5407e commit aa26728
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 6 deletions.
12 changes: 9 additions & 3 deletions src/tox_ini_fmt/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,19 @@ def run(args: Sequence[str] | None = None) -> int:
opts = cli_args(sys.argv[1:] if args is None else args)
changed = False
for tox_ini in opts.tox_ini:
formatted = format_tox_ini(tox_ini, opts)
before = tox_ini.read_text()
with tox_ini.open("rt") as file:
before = file.read()
original_newlines = file.newlines
if isinstance(original_newlines, tuple):
original_newlines = original_newlines[0]
formatted = format_tox_ini(before, opts)
changed |= before != formatted
if opts.stdout: # stdout just prints new format to stdout
print(formatted, end="")
else:
tox_ini.write_text(formatted)
if before != formatted:
with tox_ini.open("wt", newline=original_newlines) as file:
file.write(formatted)
try:
name = str(tox_ini.relative_to(Path.cwd()))
except ValueError:
Expand Down
9 changes: 6 additions & 3 deletions src/tox_ini_fmt/formatter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@
INDENTATION = " "


def format_tox_ini(tox_ini: Path, opts: ToxIniFmtNamespace | None = None) -> str:
def format_tox_ini(tox_ini: str | Path, opts: ToxIniFmtNamespace | None = None) -> str:
if opts is None:
opts = ToxIniFmtNamespace(pin_toxenvs=[])
parser = ConfigParser(interpolation=None)
with tox_ini.open("rt"):
parser.read([tox_ini])
if isinstance(tox_ini, Path):
text = tox_ini.read_text()
else:
text = tox_ini
parser.read_string(text)

order_sections(parser, opts.pin_toxenvs)
format_tox_section(parser, opts.pin_toxenvs)
Expand Down
46 changes: 46 additions & 0 deletions tests/formatter/test_line_endings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from __future__ import annotations

import os

import pytest

from tox_ini_fmt.__main__ import run


def test_platform_default(tox_ini):
"""If the ini file has no newlines, the platform default may be inserted."""

tox_ini.write_bytes(b"[tox]")
run([str(tox_ini)])
assert tox_ini.read_bytes() == f"[tox]{os.linesep}".encode()


@pytest.mark.parametrize("newline", ["\r\n", "\n", "\r"])
def test_line_endings(tox_ini, newline):
"""The ini file's existing newlines must be respected when reformatting."""

original_text = f"[tox]{newline}envlist=py39"
expected_text = f"[tox]{newline}envlist ={newline} py39{newline}"
tox_ini.write_bytes(original_text.encode("utf8"))
run([str(tox_ini)])
assert tox_ini.read_bytes() == expected_text.encode("utf8")


def test_mixed_line_endings(tox_ini):
"""If mixed line endings are found, the first one in the tuple should be used.
Note that this does not mean the first newline in the file will be used!
Python does not report the newlines in the order they're encountered.
"""

original_text = "[tox]\r\n \r \nenvlist=py39"
expected_text = "[tox]!!envlist =!! py39!!"
tox_ini.write_bytes(original_text.encode("utf8"))
with tox_ini.open("rt") as file:
file.read()
assert set(file.newlines) == {"\r", "\n", "\r\n"}
first_newline = file.newlines[0]

expected_text = expected_text.replace("!!", first_newline)
run([str(tox_ini)])
assert tox_ini.read_bytes() == expected_text.encode("utf8")

0 comments on commit aa26728

Please sign in to comment.