Skip to content

Commit

Permalink
Allow for reading TOML files from stdin. (#239)
Browse files Browse the repository at this point in the history
  • Loading branch information
fniessink authored Jul 30, 2024
1 parent 7f59a07 commit 125f7ee
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/pyproject_fmt/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def _handle_one(config: Config) -> bool:
formatted = format_toml(config.toml, config.settings)
before = config.toml
changed = before != formatted
if config.stdout: # stdout just prints new format to stdout
if config.pyproject_toml is None or config.stdout: # when reading from stdin or writing to stdout, print new format
print(formatted, end="") # noqa: T201
return changed

Expand Down
45 changes: 22 additions & 23 deletions src/pyproject_fmt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,23 @@ class PyProjectFmtNamespace(Namespace):
class Config:
"""Configuration flags for the formatting."""

pyproject_toml: Path
stdout: bool # push to standard out
pyproject_toml: Path | None # path to the toml file or None if stdin
toml: str # the toml file content
stdout: bool # push to standard out, implied if reading from stdin
check: bool # check only
no_print_diff: bool # don't print diff
settings: Settings

@property
def toml(self) -> str:
""":return: the toml files content"""
return self.pyproject_toml.read_text(encoding="utf-8")


def pyproject_toml_path_creator(argument: str) -> Path:
def pyproject_toml_path_creator(argument: str) -> Path | None:
"""
Validate that pyproject.toml can be formatted.
:param argument: the string argument passed in
:return: the pyproject.toml path
:return: the pyproject.toml path or None if stdin
"""
if argument == "-":
return None # stdin, no further validation needed
path = Path(argument).absolute()
if path.is_dir():
path /= "pyproject.toml"
Expand Down Expand Up @@ -105,7 +103,7 @@ def _build_cli() -> ArgumentParser:

mode_group = parser.add_argument_group("run mode")
mode = mode_group.add_mutually_exclusive_group()
msg = "print the formatted TOML to the stdout"
msg = "print the formatted TOML to the stdout, implied if reading from stdin"
mode.add_argument("-s", "--stdout", action="store_true", help=msg)
msg = "check and fail if any input would be formatted, printing any diffs"
mode.add_argument("--check", action="store_true", help=msg)
Expand Down Expand Up @@ -141,7 +139,7 @@ def _build_cli() -> ArgumentParser:
help="latest Python version the project supports (e.g. 3.13)",
)

msg = "pyproject.toml file(s) to format"
msg = "pyproject.toml file(s) to format, use '-' to read from stdin"
parser.add_argument(
"inputs",
nargs="+",
Expand All @@ -167,21 +165,22 @@ def cli_args(args: Sequence[str]) -> list[Config]:
indent = opt.indent
keep_full_version = opt.keep_full_version
max_supported_python = opt.max_supported_python
with pyproject_toml.open("rb") as file_handler:
config = tomllib.load(file_handler)
if "tool" in config and "pyproject-fmt" in config["tool"]:
for key, entry in config["tool"]["pyproject-fmt"].items():
if key == "column_width":
column_width = int(entry)
elif key == "indent":
indent = int(entry)
elif key == "keep_full_version":
keep_full_version = bool(entry)
elif key == "max_supported_python":
max_supported_python = _version_argument(entry)
raw_pyproject_toml = sys.stdin.read() if pyproject_toml is None else pyproject_toml.read_text(encoding="utf-8")
config = tomllib.loads(raw_pyproject_toml)
if "tool" in config and "pyproject-fmt" in config["tool"]:
for key, entry in config["tool"]["pyproject-fmt"].items():
if key == "column_width":
column_width = int(entry)
elif key == "indent":
indent = int(entry)
elif key == "keep_full_version":
keep_full_version = bool(entry)
elif key == "max_supported_python":
max_supported_python = _version_argument(entry)
res.append(
Config(
pyproject_toml=pyproject_toml,
toml=raw_pyproject_toml,
stdout=opt.stdout,
check=opt.check,
no_print_diff=opt.no_print_diff,
Expand Down
11 changes: 11 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import io
import os
import sys
from importlib.metadata import version
Expand All @@ -13,6 +14,8 @@
if TYPE_CHECKING:
from pathlib import Path

from pytest_mock import MockerFixture


def test_cli_version(capsys: pytest.CaptureFixture[str]) -> None:
with pytest.raises(SystemExit) as context:
Expand Down Expand Up @@ -65,6 +68,14 @@ def test_cli_inputs_ok(tmp_path: Path) -> None:
assert len(result) == 3


def test_cli_pyproject_toml_stdin(mocker: MockerFixture) -> None:
mocker.patch("pyproject_fmt.cli.sys.stdin", io.StringIO(""))
result = cli_args(["-"])
assert len(result) == 1
assert result[0].pyproject_toml is None
assert not result[0].toml


def test_cli_pyproject_toml_not_exists(
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
Expand Down

0 comments on commit 125f7ee

Please sign in to comment.