Skip to content

Commit

Permalink
fix: Reformat for any modification (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
kieran-ryan committed Jul 7, 2023
1 parent 6c80e86 commit f71f9d0
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 19 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This package enforces consistent formatting of pyproject.toml files, reducing me
- double quotations
- trailing commas
- indentation
- end of file newline

## Installation

Expand Down
2 changes: 1 addition & 1 deletion pyprojectsort/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

MAJOR = 0
MINOR = 2
MICRO = 1
MICRO = 2

__version__ = f"{MAJOR}.{MINOR}.{MICRO}"
15 changes: 9 additions & 6 deletions pyprojectsort/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ def _read_config_file(config: pathlib.Path) -> pathlib.Path:

def _parse_pyproject_toml(file: pathlib.Path) -> dict[str, Any]:
"""Parse pyproject.toml file."""
with file.open("rb") as pyproject_file:
return tomllib.load(pyproject_file)
with file.open("r") as pyproject_file:
return pyproject_file.read()


def reformat_pyproject(pyproject: dict | list) -> dict:
Expand All @@ -64,7 +64,7 @@ def reformat_pyproject(pyproject: dict | list) -> dict:
return pyproject


def _check_format_needed(original: dict, reformatted: dict) -> bool:
def _check_format_needed(original: str, reformatted: str) -> bool:
"""Check if there are any differences between original and reformatted."""
return original != reformatted

Expand All @@ -79,10 +79,13 @@ def main() -> None:
"""Run application."""
args = _read_cli(sys.argv[1:])
pyproject_file = _read_config_file(pathlib.Path(args.file))
pyproject_toml = _parse_pyproject_toml(pyproject_file)
reformatted_pyproject = reformat_pyproject(pyproject_toml)

will_reformat = _check_format_needed(pyproject_toml, reformatted_pyproject)
pyproject_toml: str = _parse_pyproject_toml(pyproject_file)
pyproject: dict = tomllib.loads(pyproject_toml)
reformatted_pyproject: dict = reformat_pyproject(pyproject)
reformatted_pyproject_toml: str = tomli_w.dumps(reformatted_pyproject)

will_reformat = _check_format_needed(pyproject_toml, reformatted_pyproject_toml)

if args.check:
if will_reformat:
Expand Down
66 changes: 54 additions & 12 deletions tests/unit/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,14 @@ def test_main_with_file_reformatted(
args = CLIArgs()
read_cli.return_value = args
read_config.return_value = pathlib.Path()
parse_pyproject.return_value = {}
parse_pyproject.return_value = "change = 1"
reformat_pyproject.return_value = {"change": 1}

with pytest.raises(SystemExit) as reformatted, OutputCapture() as output:
main()

assert reformatted.value.code == 1
assert output.text == f"Reformatted '{args.file}'"
assert f"Reformatted '{args.file}'" in output.text


@unittest.mock.patch("pyprojectsort.main._save_pyproject")
Expand All @@ -142,13 +142,13 @@ def test_main_with_file_unchanged(
args = CLIArgs()
read_cli.return_value = args
read_config.return_value = pathlib.Path()
parse_pyproject.return_value = {}
parse_pyproject.return_value = ""
reformat_pyproject.return_value = {}

with OutputCapture() as output:
main()

assert output.text == f"'{args.file}' left unchanged"
assert f"'{args.file}' left unchanged" in output.text


@unittest.mock.patch("pyprojectsort.main.reformat_pyproject")
Expand All @@ -165,14 +165,48 @@ def test_check_option_reformat_needed(
args = CLIArgs(check=True)
read_cli.return_value = args
read_config.return_value = pathlib.Path()
parse_pyproject.return_value = {}
parse_pyproject.return_value = "change = 1"
reformat_pyproject.return_value = {"change": 1}

with pytest.raises(SystemExit) as pytest_wrapped_e, OutputCapture() as output:
with pytest.raises(SystemExit) as would_reformat, OutputCapture() as output:
main()

assert output.text == f"'{args.file}' would be reformatted"
assert pytest_wrapped_e.value.code == 1
assert f"'{args.file}' would be reformatted" in output.text
assert would_reformat.value.code == 1


@pytest.mark.parametrize(
("original"),
[
('unsorted = [\n "tests",\n "docs",\n]\n'),
('not-indented = [\n "docs",\n"tests",\n]\n'),
('no-trailing-comma = [\n "docs",\n "tests"\n]\n'),
('not-line-per-list-value = ["docs","tests"]\n'),
('extra_spaces = "value"\n'),
('no-newline-at-end-of-file = "value"'),
("single-quotes = 'value'\n"),
],
)
@unittest.mock.patch("pyprojectsort.main._parse_pyproject_toml")
@unittest.mock.patch("pyprojectsort.main._read_config_file")
@unittest.mock.patch("pyprojectsort.main._read_cli")
def test_would_reformat(
read_cli,
read_config,
parse_pyproject,
original,
):
"""Test --check option when reformat occurs."""
args = CLIArgs(check=True)
read_cli.return_value = args
read_config.return_value = pathlib.Path()
parse_pyproject.return_value = original

with pytest.raises(SystemExit) as would_reformat, OutputCapture() as output:
main()
print(output.text)
assert f"'{args.file}' would be reformatted" in output.text
assert would_reformat.value.code == 1


@unittest.mock.patch("pyprojectsort.main.reformat_pyproject")
Expand All @@ -189,20 +223,28 @@ def test_check_option_reformat_not_needed(
args = CLIArgs(check=True)
read_cli.return_value = args
read_config.return_value = pathlib.Path()
parse_pyproject.return_value = {"unchanged": 1}
parse_pyproject.return_value = "unchanged = 1\n"
reformat_pyproject.return_value = {"unchanged": 1}

with OutputCapture() as output:
main()

assert output.text == f"'{args.file}' would be left unchanged"
assert f"'{args.file}' would be left unchanged" in output.text


@pytest.mark.parametrize(
("original", "reformatted", "expected_result"),
[
({"unchanged": 1}, {"unchanged": 1}, False),
({"should_be_changed": 1}, {"changed": 1}, True),
(
'[tool.pylint]\nignore = [\n\t"tests",\n\t"docs",\n]',
'[tool.pylint]\nignore = [\n\t"tests",\n\t"docs",\n]',
False,
),
(
'[tool.pylint]\nignore = [\n\t"tests",\n\t"docs",\n]',
'[tool.pylint]\nignore = [\n\t"docs",\n\t"tests",\n]',
True,
),
],
)
def test_check_format_needed(original, reformatted, expected_result):
Expand Down

0 comments on commit f71f9d0

Please sign in to comment.