Skip to content

Commit

Permalink
Migrate to version 2 powered by pyproject-fmt-rust (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
gaborbernat committed May 10, 2024
1 parent 19d88ef commit 495d968
Show file tree
Hide file tree
Showing 20 changed files with 213 additions and 1,878 deletions.
32 changes: 19 additions & 13 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.4",
"hatchling>=1.18",
"hatchling>=1.24.2",
]

[project]
Expand Down Expand Up @@ -31,22 +31,20 @@ dynamic = [
"version",
]
dependencies = [
"natsort>=8.4",
"packaging>=23.2",
"tomlkit>=0.12.3",
"pyproject-fmt-rust==1",
]
optional-dependencies.docs = [
"furo>=2023.9.10",
"sphinx>=7.2.6",
"sphinx-argparse-cli>=1.11.1",
"sphinx-autodoc-typehints>=1.25.2",
"furo>=2024.5.6",
"sphinx>=7.3.7",
"sphinx-argparse-cli>=1.15",
"sphinx-autodoc-typehints>=2.1",
"sphinx-copybutton>=0.5.2",
]
optional-dependencies.test = [
"covdefaults>=2.3",
"pytest>=7.4.3",
"pytest-cov>=4.1",
"pytest-mock>=3.12",
"pytest>=8.2",
"pytest-cov>=5",
"pytest-mock>=3.14",
]
urls."Bug Tracker" = "https://github.com/tox-dev/pyproject-fmt/issues"
urls."Changelog" = "https://github.com/tox-dev/pyproject-fmt/releases"
Expand Down Expand Up @@ -102,8 +100,16 @@ ini_options.testpaths = ["tests"]
[tool.coverage]
html.show_contexts = true
html.skip_covered = false
paths.source = ["src", ".tox/*/lib/python*/site-packages", "*/src"]
report.fail_under = 88
paths.source = [
"src",
".tox/*/.venv/lib/*/site-packages",
".tox\\*\\.venv\\Lib\\site-packages",
".tox/*/lib/*/site-packages",
".tox\\*\\Lib\\site-packages",
"**/src",
"**\\src",
]
report.fail_under = 100
run.parallel = true
run.plugins = ["covdefaults"]

Expand Down
9 changes: 2 additions & 7 deletions src/pyproject_fmt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
"""Format your pyproject.toml."""
"""Package root."""

from __future__ import annotations

from ._version import version as __version__
from .formatter import format_pyproject
from .formatter.config import Config, PyProjectConfig
from ._version import __version__

__all__ = [
"Config",
"PyProjectConfig",
"__version__",
"format_pyproject",
]
26 changes: 17 additions & 9 deletions src/pyproject_fmt/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
from pathlib import Path
from typing import TYPE_CHECKING, Iterable, Sequence

from pyproject_fmt.cli import PyProjectFmtNamespace, cli_args
from pyproject_fmt.formatter import format_pyproject
from pyproject_fmt_rust import format_toml

from pyproject_fmt.cli import cli_args

if TYPE_CHECKING:
from pyproject_fmt import Config
from pyproject_fmt.cli import Config

GREEN = "\u001b[32m"
RED = "\u001b[31m"
Expand All @@ -33,15 +34,22 @@ def color_diff(diff: Iterable[str]) -> Iterable[str]:
yield line


def _handle_one(config: Config, opts: PyProjectFmtNamespace) -> bool:
formatted = format_pyproject(config)
def _handle_one(config: Config) -> bool:
formatted = format_toml(
config.toml,
column_width=config.column_width,
indent=config.indent,
keep_full_version=config.keep_full_version,
max_supported_python=(config.max_supported_python.major, config.max_supported_python.minor),
min_supported_python=(config.min_supported_python.major, config.min_supported_python.minor),
)
before = config.toml
changed = before != formatted
if opts.stdout: # stdout just prints new format to stdout
if config.stdout: # stdout just prints new format to stdout
print(formatted, end="") # noqa: T201
return changed

if before != formatted and not opts.check:
if before != formatted and not config.check:
config.pyproject_toml.write_text(formatted, encoding="utf-8")
try:
name = str(config.pyproject_toml.relative_to(Path.cwd()))
Expand All @@ -66,8 +74,8 @@ def run(args: Sequence[str] | None = None) -> int:
:param args: CLI arguments
:return: exit code
"""
opts = cli_args(sys.argv[1:] if args is None else args)
results = [_handle_one(config, opts) for config in opts.configs]
configs = cli_args(sys.argv[1:] if args is None else args)
results = [_handle_one(config) for config in configs]
return 1 if any(results) else 0 # exit with non success on change


Expand Down
108 changes: 85 additions & 23 deletions src/pyproject_fmt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,60 @@

from __future__ import annotations

import sys
from dataclasses import dataclass

if sys.version_info >= (3, 11): # pragma: >=3.11 cover
import tomllib
else: # pragma: <3.11 cover
import tomli as tomllib

import os
from argparse import (
ArgumentDefaultsHelpFormatter,
ArgumentParser,
ArgumentTypeError,
Namespace,
)
from importlib.metadata import version
from pathlib import Path
from typing import Sequence

from packaging.version import Version

from ._version import __version__
from .formatter.config import DEFAULT_INDENT, DEFAULT_MAX_SUPPORTED_PYTHON, Config


class PyProjectFmtNamespace(Namespace):
"""Options for pyproject-fmt tool."""

inputs: list[Path]
stdout: bool
indent: int
check: bool

column_width: int
indent: int
keep_full_version: bool
max_supported_python: Version
min_supported_python: Version


@dataclass(frozen=True)
class Config:
"""Configuration flags for the formatting."""

pyproject_toml: Path
stdout: bool # push to standard out
check: bool # check only

column_width: int #: maximum column width
indent: int #: indentation to apply
keep_full_version: bool #: whether to keep full dependency versions
max_supported_python: Version #: the maximum supported Python version
min_supported_python: Version #: the minimum supported Python version

@property
def configs(self) -> list[Config]:
""":return: configurations"""
return [
Config(
pyproject_toml=toml,
toml=toml.read_text(encoding="utf-8"),
indent=self.indent,
keep_full_version=self.keep_full_version,
max_supported_python=self.max_supported_python,
)
for toml in self.inputs
]
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:
Expand Down Expand Up @@ -78,7 +93,7 @@ def _build_cli() -> ArgumentParser:
"--version",
action="version",
help="print package version of pyproject_fmt",
version=f"%(prog)s ({__version__})",
version=f"%(prog)s ({version('pyproject-fmt')})",
)
group = parser.add_mutually_exclusive_group()
msg = "print the formatted text to the stdout (instead of update in-place)"
Expand All @@ -87,37 +102,84 @@ def _build_cli() -> ArgumentParser:
group.add_argument("--check", action="store_true", help=msg)
msg = "keep full dependency versions. For example do not change version 1.0.0 to 1"
parser.add_argument("--keep-full-version", action="store_true", help=msg)
parser.add_argument(
"--column-width",
type=int,
default=1,
help="max column width in the file",
)
parser.add_argument(
"--indent",
type=int,
default=DEFAULT_INDENT,
default=2,
help="number of spaces to indent",
)
parser.add_argument(
"--min-supported-python",
type=Version,
default="3.8",
help="latest Python version the project supports (e.g. 3.8)",
)
parser.add_argument(
"--max-supported-python",
type=Version,
default=DEFAULT_MAX_SUPPORTED_PYTHON,
default="3.12",
help="latest Python version the project supports (e.g. 3.13)",
)
msg = "pyproject.toml file(s) to format"
parser.add_argument("inputs", nargs="+", type=pyproject_toml_path_creator, help=msg)
return parser


def cli_args(args: Sequence[str]) -> PyProjectFmtNamespace:
def cli_args(args: Sequence[str]) -> list[Config]:
"""
Load the tools options.
:param args: CLI arguments
:return: the parsed options
"""
parser = _build_cli()
result = PyProjectFmtNamespace()
parser.parse_args(namespace=result, args=args)
return result
opt = PyProjectFmtNamespace()
parser.parse_args(namespace=opt, args=args)
res = []
for pyproject_toml in opt.inputs:
column_width = opt.column_width
indent = opt.indent
keep_full_version = opt.keep_full_version
max_supported_python = opt.max_supported_python
min_supported_python = opt.min_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(entry)
elif key == "min_supported_python": # pragma: no branch
min_supported_python = Version(entry)
res.append(
Config(
pyproject_toml=pyproject_toml,
stdout=opt.stdout,
check=opt.check,
column_width=column_width,
indent=indent,
keep_full_version=keep_full_version,
max_supported_python=max_supported_python,
min_supported_python=min_supported_python,
)
)

return res


__all__ = [
"Config",
"PyProjectFmtNamespace",
"cli_args",
]
43 changes: 0 additions & 43 deletions src/pyproject_fmt/formatter/__init__.py

This file was deleted.

39 changes: 0 additions & 39 deletions src/pyproject_fmt/formatter/build_system.py

This file was deleted.

Loading

0 comments on commit 495d968

Please sign in to comment.