-
Notifications
You must be signed in to change notification settings - Fork 26
/
cli.py
122 lines (105 loc) · 3.44 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""CLI interface parser."""
from __future__ import annotations
import os
from argparse import (
ArgumentDefaultsHelpFormatter,
ArgumentParser,
ArgumentTypeError,
Namespace,
)
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
keep_full_version: bool
max_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 pyproject_toml_path_creator(argument: str) -> Path:
"""
Validate that pyproject.toml can be formatted.
:param argument: the string argument passed in
:return: the pyproject.toml path
"""
path = Path(argument).absolute()
if path.is_dir():
path = path / "pyproject.toml"
if not path.exists():
msg = "path does not exist"
raise ArgumentTypeError(msg)
if not path.is_file():
msg = "path is not a file"
raise ArgumentTypeError(msg)
if not os.access(path, os.R_OK):
msg = "cannot read path"
raise ArgumentTypeError(msg)
if not os.access(path, os.W_OK):
msg = "cannot write path"
raise ArgumentTypeError(msg)
return path
def _build_cli() -> ArgumentParser:
parser = ArgumentParser(
formatter_class=ArgumentDefaultsHelpFormatter,
prog="pyproject-fmt",
)
parser.add_argument(
"-V",
"--version",
action="version",
help="print package version of pyproject_fmt",
version=f"%(prog)s ({__version__})",
)
group = parser.add_mutually_exclusive_group()
msg = "print the formatted text to the stdout (instead of update in-place)"
group.add_argument("-s", "--stdout", action="store_true", help=msg)
msg = "check and fail if any input would be formatted, printing any diffs"
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(
"--indent",
type=int,
default=DEFAULT_INDENT,
help="number of spaces to indent",
)
parser.add_argument(
"--max-supported-python",
type=Version,
default=DEFAULT_MAX_SUPPORTED_PYTHON,
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:
"""
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
__all__ = [
"cli_args",
"PyProjectFmtNamespace",
]