Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ repos:
additional_dependencies:
- flake8-bugbear==23.1.20
- flake8-comprehensions==3.10.1
- flake8-pytest-style==1.6
- flake8-pytest-style==1.7
- flake8-spellcheck==0.28
- flake8-unused-arguments==0.0.13
- flake8-noqa==1.3
Expand Down
37 changes: 0 additions & 37 deletions docs/changelog.rst

This file was deleted.

2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pyproject-fmt
=============

Apply a consistent format to your ``pyproject.toml`` file with comment support.
See `changelog here <https://github.com/tox-dev/pyproject-fmt/releases>`_.

Use
---
Expand Down Expand Up @@ -46,4 +47,3 @@ API
:hidden:

self
changelog
22 changes: 11 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
build-backend = "hatchling.build"
requires = [
"hatch-vcs>=0.3",
"hatchling>=1.12.2",
"hatchling>=1.13",
]

[project]
Expand Down Expand Up @@ -39,7 +39,7 @@ optional-dependencies.docs = [
"furo>=2022.12.7",
"sphinx>=6.1.3",
"sphinx-argparse-cli>=1.11",
"sphinx-autodoc-typehints!=1.23.4,>1",
"sphinx-autodoc-typehints!=1.23.4,>=1.22",
"sphinx-copybutton>=0.5.1",
]
optional-dependencies.test = [
Expand All @@ -51,22 +51,28 @@ optional-dependencies.test = [
urls."Bug Tracker" = "https://github.com/tox-dev/pyproject-fmt/issues"
urls.Documentation = "https://github.com/tox-dev/pyproject-fmt/"
urls."Source Code" = "https://github.com/tox-dev/pyproject-fmt"
urls."Changelog" = "https://github.com/tox-dev/pyproject-fmt/releases"
scripts.pyproject-fmt = "pyproject_fmt.__main__:run"


[tool.hatch]
build.dev-mode-dirs = ["src"]
build.hooks.vcs.version-file = "src/pyproject_fmt/_version.py"
build.targets.sdist.include = ["/src", "/tests"]
version.source = "vcs"

[tool.black]
line-length = 120

[tool.isort]
known_first_party = ["helpers", "package_info"]
profile = "black"
add_imports = ["from __future__ import annotations"]

[tool.black]
line-length = 120
[tool.flake8]
max-line-length = 120
unused-arguments-ignore-abstract-functions = true
noqa-require-code = true
dictionaries = ["en_US", "python", "technical", "django"]

[tool.pytest]
ini_options.testpaths = ["tests"]
Expand All @@ -82,9 +88,3 @@ run.plugins = ["covdefaults"]
[tool.mypy]
show_error_codes = true
strict = true

[tool.flake8]
max-line-length = 120
unused-arguments-ignore-abstract-functions = true
noqa-require-code = true
dictionaries = ["en_US", "python", "technical", "django"]
2 changes: 2 additions & 0 deletions src/pyproject_fmt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ def pyproject_toml_path_creator(argument: str) -> Path:
:return: the pyproject.toml path
"""
path = Path(argument).absolute()
if path.is_dir():
path = path / "pyproject.toml"
if not path.exists():
raise ArgumentTypeError("path does not exist")
if not path.is_file():
Expand Down
2 changes: 2 additions & 0 deletions src/pyproject_fmt/formatter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
from .build_system import fmt_build_system
from .config import Config
from .project import fmt_project
from .tools import fmt_tools


def _perform(parsed: TOMLDocument, conf: Config) -> None:
fmt_build_system(parsed, conf)
fmt_project(parsed, conf)
fmt_tools(parsed, conf)


def format_pyproject(conf: Config) -> str:
Expand Down
3 changes: 2 additions & 1 deletion src/pyproject_fmt/formatter/build_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .config import Config
from .pep508 import normalize_pep508_array
from .util import order_keys, sorted_array
from .util import ensure_newline_at_end, order_keys, sorted_array


def fmt_build_system(parsed: TOMLDocument, conf: Config) -> None:
Expand All @@ -16,6 +16,7 @@ def fmt_build_system(parsed: TOMLDocument, conf: Config) -> None:
normalize_pep508_array(cast(Optional[Array], system.get("requires")), conf.indent)
sorted_array(cast(Optional[Array], system.get("backend-path")), indent=conf.indent)
order_keys(system, ("build-backend", "requires", "backend-path"))
ensure_newline_at_end(system)


__all__ = [
Expand Down
3 changes: 2 additions & 1 deletion src/pyproject_fmt/formatter/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from .config import Config
from .pep508 import normalize_pep508_array
from .util import order_keys, sorted_array
from .util import ensure_newline_at_end, order_keys, sorted_array


def fmt_project(parsed: TOMLDocument, conf: Config) -> None:
Expand Down Expand Up @@ -56,6 +56,7 @@ def fmt_project(parsed: TOMLDocument, conf: Config) -> None:
# these go at the end as they may be inline or exploded
key_order.extend(["optional-dependencies", "urls", "scripts", "gui-scripts", "entry-points"])
order_keys(project, key_order)
ensure_newline_at_end(project)


__all__ = [
Expand Down
24 changes: 24 additions & 0 deletions src/pyproject_fmt/formatter/tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from __future__ import annotations

from typing import cast

from tomlkit import TOMLDocument
from tomlkit.items import Table

from .config import Config
from .util import ensure_newline_at_end, order_keys


def fmt_tools(parsed: TOMLDocument, conf: Config) -> None: # noqa: U100
tools: Table | None = parsed.get("tool")
if tools is None:
return None
for tool in tools:
table = tools[tool]
ensure_newline_at_end(cast(Table, table))
order_keys(tools, to_pin=["setuptools", "hatch", "black", "isort", "flake8", "pytest", "coverage", "mypy"])


__all__ = [
"fmt_tools",
]
16 changes: 13 additions & 3 deletions src/pyproject_fmt/formatter/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ def order_keys(
for _, elements in sorted(entries.items(), key=sort_inline_table):
body.extend(elements)

if isinstance(table, Table):
body.append((None, Whitespace("\n"))) # add trailing newline to separate


@dataclass
class ArrayEntries:
Expand Down Expand Up @@ -109,8 +106,21 @@ def sorted_array(
body.append(_ArrayItemGroup(indent=Whitespace("\n")))


def ensure_newline_at_end(body: Table) -> None:
content = body
while content.value.body and isinstance(content.value.body[-1][1], Table):
content = content.value.body[-1][1]
whitespace = Whitespace("\n")
insert_body = content.value.body
if insert_body and isinstance(insert_body[-1][1], Whitespace):
insert_body[-1] = insert_body[-1][0], whitespace
else:
insert_body.append((None, whitespace))


__all__ = [
"ArrayEntries",
"sorted_array",
"order_keys",
"ensure_newline_at_end",
]
4 changes: 3 additions & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@

Fmt = Callable[[Callable[[TOMLDocument, Config], None], str, str], None]

__all__ = ["Fmt"]
__all__ = [
"Fmt",
]
45 changes: 45 additions & 0 deletions tests/formatter/test_tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from __future__ import annotations

from pyproject_fmt.formatter.tools import fmt_tools
from tests import Fmt


def test_tools_ordering(fmt: Fmt) -> None:
content = """
[tool.coverage]
a = 0
[tool.pytest]
a = 0
[tool.black]
a = 0
[tool.isort]
a = 0
[tool.flake8]
[tool.hatch]
a = 0
[tool.setuptools]
a.b = 0

"""
expected = """
[tool.setuptools]
a.b = 0

[tool.hatch]
a = 0

[tool.black]
a = 0

[tool.isort]
a = 0

[tool.flake8]

[tool.pytest]
a = 0

[tool.coverage]
a = 0
"""
fmt(fmt_tools, content, expected)
10 changes: 9 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import os
import sys
from pathlib import Path
from stat import S_IREAD, S_IWRITE
Expand Down Expand Up @@ -36,8 +37,10 @@ def test_cli_pyproject_toml_not_exists(tmp_path: Path, capsys: pytest.CaptureFix


def test_cli_pyproject_toml_not_file(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None:
path = tmp_path / "temp"
os.mkfifo(path)
with pytest.raises(SystemExit) as context:
cli_args([str(tmp_path)])
cli_args([str(path)])
assert context.value.code != 0
out, err = capsys.readouterr()
assert not out
Expand Down Expand Up @@ -69,3 +72,8 @@ def test_pyproject_toml_resolved(tmp_path: Path, monkeypatch: pytest.MonkeyPatch
path.write_text("")
result = cli_args(["tox.ini"])
assert result.inputs == [path]


def test_pyproject_toml_dir(tmp_path: Path) -> None:
(tmp_path / "pyproject.toml").write_text("")
cli_args([str(tmp_path)])
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ description = run type check on code base
setenv =
{tty:MYPY_FORCE_COLOR = 1}
deps =
mypy==0.991
mypy==1
commands =
mypy --strict --python-version 3.10 src tests

Expand Down
11 changes: 1 addition & 10 deletions whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,23 @@ autodoc
canonicalize
capsys
chdir
conf
configs
deps
difflib
dunder
extlinks
fmt
formatter
fromfile
func
intersphinx
iread
iwrite
mkfifo
nitpicky
pep508
py38
pygments
pyproject
raws
readouterr
req
sdist
skipif
tmp
tofile
toml
tomlkit
typehints
util