pyprojkit 0.4.2__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/PKG-INFO +2 -2
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/pyproject.toml +6 -5
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/__init__.py +4 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/config/__init__.py +4 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/config/base.py +25 -4
- pyprojkit-0.5.0/src/pyprojkit/config/profiles.py +51 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/config/project.py +103 -30
- pyprojkit-0.5.0/src/pyprojkit/config/tools.py +247 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/sessions.py +1 -1
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/sync.py +8 -12
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/tasks.py +1 -1
- pyprojkit-0.4.2/src/pyprojkit/config/profiles.py +0 -69
- pyprojkit-0.4.2/src/pyprojkit/config/tools.py +0 -175
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/LICENSE +0 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/README.md +0 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/_paths.py +0 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/_run.py +0 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/cli.py +0 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/discovery.py +0 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/skill.py +0 -0
- {pyprojkit-0.4.2 → pyprojkit-0.5.0}/src/pyprojkit/versions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyprojkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Development workflow toolkit for Python projects: pyproject.toml sync, doit tasks, nox sessions
|
|
5
5
|
Author: mm21
|
|
6
6
|
Author-email: mm21 <mm21.dev@gmail.com>
|
|
@@ -24,7 +24,7 @@ Requires-Dist: tomlkit>=0.13.3,<0.14
|
|
|
24
24
|
Requires-Dist: pyprojkit[analysis,doc,format,test] ; extra == 'all'
|
|
25
25
|
Requires-Dist: mypy[reports]>=1.5.1,<2 ; extra == 'analysis'
|
|
26
26
|
Requires-Dist: pyright>=1.1.329,<2 ; extra == 'analysis'
|
|
27
|
-
Requires-Dist: mkinit ; extra == 'doc'
|
|
27
|
+
Requires-Dist: mkinit>=1.3.0,<2 ; extra == 'doc'
|
|
28
28
|
Requires-Dist: autoflake>=2.3.1,<3 ; extra == 'format'
|
|
29
29
|
Requires-Dist: black>=25.1.0,<26 ; extra == 'format'
|
|
30
30
|
Requires-Dist: docfmt>=0.3.0,<0.4.0 ; extra == 'format'
|
|
@@ -29,7 +29,7 @@ license-files = ["LICENSE"]
|
|
|
29
29
|
name = "pyprojkit"
|
|
30
30
|
readme = "README.md"
|
|
31
31
|
requires-python = ">=3.12,<4.0" # pyprojkit-managed
|
|
32
|
-
version = "0.
|
|
32
|
+
version = "0.5.0"
|
|
33
33
|
|
|
34
34
|
[project.optional-dependencies]
|
|
35
35
|
all = [
|
|
@@ -40,7 +40,7 @@ analysis = [
|
|
|
40
40
|
"pyright>=1.1.329,<2"
|
|
41
41
|
]
|
|
42
42
|
doc = [
|
|
43
|
-
"mkinit"
|
|
43
|
+
"mkinit>=1.3.0,<2"
|
|
44
44
|
]
|
|
45
45
|
format = [
|
|
46
46
|
"autoflake>=2.3.1,<3",
|
|
@@ -107,6 +107,7 @@ profile = "black" # pyprojkit-managed
|
|
|
107
107
|
quiet = true # pyprojkit-managed
|
|
108
108
|
|
|
109
109
|
[tool.mypy]
|
|
110
|
+
check_untyped_defs = true # pyprojkit-managed
|
|
110
111
|
ignore_missing_imports = true # pyprojkit-managed
|
|
111
112
|
python_version = "3.12" # pyprojkit-managed
|
|
112
113
|
|
|
@@ -114,6 +115,9 @@ python_version = "3.12" # pyprojkit-managed
|
|
|
114
115
|
default_venv_backend = "uv" # pyprojkit-managed
|
|
115
116
|
envdir = "__cache__/nox" # pyprojkit-managed
|
|
116
117
|
|
|
118
|
+
[tool.pyright]
|
|
119
|
+
pythonVersion = "3.12" # pyprojkit-managed
|
|
120
|
+
|
|
117
121
|
[tool.pytest.ini_options]
|
|
118
122
|
addopts = "--import-mode=importlib -s -v -rA" # pyprojkit-managed
|
|
119
123
|
cache_dir = "__cache__/pytest" # pyprojkit-managed
|
|
@@ -127,6 +131,3 @@ sort_first = [
|
|
|
127
131
|
] # pyprojkit-managed
|
|
128
132
|
sort_table_keys = true # pyprojkit-managed
|
|
129
133
|
spaces_before_inline_comment = 2 # pyprojkit-managed
|
|
130
|
-
|
|
131
|
-
[tool.uv.sources]
|
|
132
|
-
mkinit = {git = "https://github.com/mm21/mkinit.git"}
|
|
@@ -19,6 +19,7 @@ __submodules__ = [
|
|
|
19
19
|
# <AUTOGEN_INIT>
|
|
20
20
|
from .config import (
|
|
21
21
|
ConfigError,
|
|
22
|
+
BaseConfig,
|
|
22
23
|
BaseToolConfig,
|
|
23
24
|
BaseFormatterConfig,
|
|
24
25
|
AutoflakeConfig,
|
|
@@ -32,6 +33,7 @@ from .config import (
|
|
|
32
33
|
DoitConfig,
|
|
33
34
|
NoxConfig,
|
|
34
35
|
MypyConfig,
|
|
36
|
+
PyrightConfig,
|
|
35
37
|
ProjectConfig,
|
|
36
38
|
ToolsConfig,
|
|
37
39
|
FormattingConfig,
|
|
@@ -71,6 +73,7 @@ from .sessions import (
|
|
|
71
73
|
__all__ = [
|
|
72
74
|
"sync",
|
|
73
75
|
"ConfigError",
|
|
76
|
+
"BaseConfig",
|
|
74
77
|
"BaseToolConfig",
|
|
75
78
|
"BaseFormatterConfig",
|
|
76
79
|
"AutoflakeConfig",
|
|
@@ -84,6 +87,7 @@ __all__ = [
|
|
|
84
87
|
"DoitConfig",
|
|
85
88
|
"NoxConfig",
|
|
86
89
|
"MypyConfig",
|
|
90
|
+
"PyrightConfig",
|
|
87
91
|
"ProjectConfig",
|
|
88
92
|
"ToolsConfig",
|
|
89
93
|
"FormattingConfig",
|
|
@@ -13,6 +13,7 @@ __submodules__ = [
|
|
|
13
13
|
# <AUTOGEN_INIT>
|
|
14
14
|
from .base import (
|
|
15
15
|
ConfigError,
|
|
16
|
+
BaseConfig,
|
|
16
17
|
BaseToolConfig,
|
|
17
18
|
BaseFormatterConfig,
|
|
18
19
|
)
|
|
@@ -28,6 +29,7 @@ from .tools import (
|
|
|
28
29
|
DoitConfig,
|
|
29
30
|
NoxConfig,
|
|
30
31
|
MypyConfig,
|
|
32
|
+
PyrightConfig,
|
|
31
33
|
)
|
|
32
34
|
from .project import (
|
|
33
35
|
ProjectConfig,
|
|
@@ -47,6 +49,7 @@ from .profiles import (
|
|
|
47
49
|
|
|
48
50
|
__all__ = [
|
|
49
51
|
"ConfigError",
|
|
52
|
+
"BaseConfig",
|
|
50
53
|
"BaseToolConfig",
|
|
51
54
|
"BaseFormatterConfig",
|
|
52
55
|
"AutoflakeConfig",
|
|
@@ -60,6 +63,7 @@ __all__ = [
|
|
|
60
63
|
"DoitConfig",
|
|
61
64
|
"NoxConfig",
|
|
62
65
|
"MypyConfig",
|
|
66
|
+
"PyrightConfig",
|
|
63
67
|
"ProjectConfig",
|
|
64
68
|
"ToolsConfig",
|
|
65
69
|
"FormattingConfig",
|
|
@@ -6,13 +6,14 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
from abc import ABC, abstractmethod
|
|
8
8
|
from dataclasses import dataclass, fields
|
|
9
|
-
from typing import TYPE_CHECKING, Any, ClassVar
|
|
9
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Self
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
12
|
from .project import ProjectConfig
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
15
15
|
"ConfigError",
|
|
16
|
+
"BaseConfig",
|
|
16
17
|
"BaseToolConfig",
|
|
17
18
|
"BaseFormatterConfig",
|
|
18
19
|
]
|
|
@@ -24,16 +25,36 @@ class ConfigError(Exception):
|
|
|
24
25
|
"""
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
class BaseConfig(ABC):
|
|
29
|
+
"""
|
|
30
|
+
Base for all tool configurations: both tool categories (e.g. `TestConfig`) and
|
|
31
|
+
individual tools' `pyproject.toml` tables (e.g. `PytestConfig`).
|
|
32
|
+
|
|
33
|
+
A default-constructed config is empty: every setting is unset and every optional
|
|
34
|
+
sub-config is disabled. Opinionated settings are provided by
|
|
35
|
+
`create_kitchen_sink()`.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def create_kitchen_sink(cls) -> Self:
|
|
41
|
+
"""
|
|
42
|
+
Get a new instance with opinionated settings, as used by
|
|
43
|
+
`create_kitchen_sink_tools()`.
|
|
44
|
+
"""
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
|
|
27
48
|
@dataclass(kw_only=True)
|
|
28
|
-
class BaseToolConfig(
|
|
49
|
+
class BaseToolConfig(BaseConfig):
|
|
29
50
|
"""
|
|
30
51
|
Configuration for a tool which reads its settings from a table in `pyproject.toml`,
|
|
31
52
|
e.g. `[tool.black]`.
|
|
32
53
|
|
|
33
54
|
Dataclass fields map to table entries; a field whose name differs from its TOML key
|
|
34
55
|
declares the key via `field(metadata={"toml": "some-key"})`. Fields set to `None`
|
|
35
|
-
are omitted. Values derived from project-wide config
|
|
36
|
-
are contributed by `extra_toml()`.
|
|
56
|
+
(the default for every field) are omitted. Values derived from project-wide config
|
|
57
|
+
(e.g. black's `target-version`) are contributed by `extra_toml()`.
|
|
37
58
|
"""
|
|
38
59
|
|
|
39
60
|
table_path: ClassVar[str]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Built-in tool configurations.
|
|
3
|
+
|
|
4
|
+
Configurations are plain `ToolsConfig` values: define your own factory function or
|
|
5
|
+
global in a module shared across projects, enabling just the tools you want:
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from pyprojkit import (
|
|
9
|
+
AnalysisConfig,
|
|
10
|
+
BlackConfig,
|
|
11
|
+
FormattingConfig,
|
|
12
|
+
IsortConfig,
|
|
13
|
+
PyrightConfig,
|
|
14
|
+
PytestConfig,
|
|
15
|
+
TestConfig,
|
|
16
|
+
ToolsConfig,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def create_mycompany_tools() -> ToolsConfig:
|
|
21
|
+
return ToolsConfig(
|
|
22
|
+
formatting=FormattingConfig(
|
|
23
|
+
formatters=(
|
|
24
|
+
IsortConfig(profile="black"),
|
|
25
|
+
BlackConfig(),
|
|
26
|
+
)
|
|
27
|
+
),
|
|
28
|
+
test=TestConfig(pytest=PytestConfig(testpaths="tests")),
|
|
29
|
+
analysis=AnalysisConfig(pyright=PyrightConfig()),
|
|
30
|
+
)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Alternatively, start from `create_kitchen_sink_tools()` and override parts of it with
|
|
34
|
+
`dataclasses.replace()`.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
from .project import ToolsConfig
|
|
40
|
+
|
|
41
|
+
__all__ = [
|
|
42
|
+
"create_kitchen_sink_tools",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def create_kitchen_sink_tools() -> ToolsConfig:
|
|
47
|
+
"""
|
|
48
|
+
Get a new instance of the configuration which enables every tool; equivalent to
|
|
49
|
+
`ToolsConfig.create_kitchen_sink()`.
|
|
50
|
+
"""
|
|
51
|
+
return ToolsConfig.create_kitchen_sink()
|
|
@@ -6,18 +6,24 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Literal, Sequence
|
|
9
|
+
from typing import Literal, Self, Sequence
|
|
10
10
|
|
|
11
11
|
from .. import _paths
|
|
12
12
|
from ..versions import PythonVersions, PythonVersionSet, RequiresPython
|
|
13
|
-
from .base import BaseFormatterConfig
|
|
13
|
+
from .base import BaseConfig, BaseFormatterConfig
|
|
14
14
|
from .tools import (
|
|
15
|
+
AutoflakeConfig,
|
|
16
|
+
BlackConfig,
|
|
15
17
|
CoverageReportConfig,
|
|
16
18
|
CoverageRunConfig,
|
|
19
|
+
DocfmtConfig,
|
|
17
20
|
DoitConfig,
|
|
21
|
+
IsortConfig,
|
|
18
22
|
MypyConfig,
|
|
19
23
|
NoxConfig,
|
|
24
|
+
PyrightConfig,
|
|
20
25
|
PytestConfig,
|
|
26
|
+
TomlSortConfig,
|
|
21
27
|
)
|
|
22
28
|
|
|
23
29
|
__all__ = [
|
|
@@ -35,19 +41,31 @@ __all__ = [
|
|
|
35
41
|
|
|
36
42
|
|
|
37
43
|
@dataclass(kw_only=True)
|
|
38
|
-
class FormattingConfig:
|
|
44
|
+
class FormattingConfig(BaseConfig):
|
|
39
45
|
"""
|
|
40
46
|
Formatting configuration: which formatters run (in order) and their settings.
|
|
41
47
|
"""
|
|
42
48
|
|
|
43
|
-
formatters: tuple[BaseFormatterConfig, ...]
|
|
49
|
+
formatters: tuple[BaseFormatterConfig, ...] = ()
|
|
44
50
|
"""
|
|
45
51
|
Formatters in run order.
|
|
46
52
|
"""
|
|
47
53
|
|
|
54
|
+
@classmethod
|
|
55
|
+
def create_kitchen_sink(cls) -> Self:
|
|
56
|
+
return cls(
|
|
57
|
+
formatters=(
|
|
58
|
+
AutoflakeConfig.create_kitchen_sink(),
|
|
59
|
+
IsortConfig.create_kitchen_sink(),
|
|
60
|
+
DocfmtConfig.create_kitchen_sink(),
|
|
61
|
+
BlackConfig.create_kitchen_sink(),
|
|
62
|
+
TomlSortConfig.create_kitchen_sink(),
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
|
|
48
66
|
|
|
49
67
|
@dataclass(kw_only=True)
|
|
50
|
-
class TestConfig:
|
|
68
|
+
class TestConfig(BaseConfig):
|
|
51
69
|
"""
|
|
52
70
|
Testing configuration (pytest + coverage).
|
|
53
71
|
"""
|
|
@@ -56,27 +74,35 @@ class TestConfig:
|
|
|
56
74
|
coverage_run: CoverageRunConfig = field(default_factory=CoverageRunConfig)
|
|
57
75
|
coverage_report: CoverageReportConfig = field(default_factory=CoverageReportConfig)
|
|
58
76
|
|
|
77
|
+
@classmethod
|
|
78
|
+
def create_kitchen_sink(cls) -> Self:
|
|
79
|
+
return cls(
|
|
80
|
+
pytest=PytestConfig.create_kitchen_sink(),
|
|
81
|
+
coverage_run=CoverageRunConfig.create_kitchen_sink(),
|
|
82
|
+
coverage_report=CoverageReportConfig.create_kitchen_sink(),
|
|
83
|
+
)
|
|
84
|
+
|
|
59
85
|
|
|
60
86
|
@dataclass(kw_only=True)
|
|
61
|
-
class MkinitConfig:
|
|
87
|
+
class MkinitConfig(BaseConfig):
|
|
62
88
|
"""
|
|
63
89
|
Configuration for generating `__init__.py` files using mkinit.
|
|
64
90
|
"""
|
|
65
91
|
|
|
66
|
-
args: tuple[str, ...] = (
|
|
67
|
-
"--recursive",
|
|
68
|
-
"--nomods",
|
|
69
|
-
"--relative",
|
|
70
|
-
"-i",
|
|
71
|
-
"--source-order",
|
|
72
|
-
)
|
|
92
|
+
args: tuple[str, ...] = ()
|
|
73
93
|
"""
|
|
74
94
|
Arguments passed to mkinit.
|
|
75
95
|
"""
|
|
76
96
|
|
|
97
|
+
@classmethod
|
|
98
|
+
def create_kitchen_sink(cls) -> Self:
|
|
99
|
+
return cls(
|
|
100
|
+
args=("--recursive", "--nomods", "--relative", "-i", "--source-order")
|
|
101
|
+
)
|
|
102
|
+
|
|
77
103
|
|
|
78
104
|
@dataclass(kw_only=True)
|
|
79
|
-
class SphinxConfig:
|
|
105
|
+
class SphinxConfig(BaseConfig):
|
|
80
106
|
"""
|
|
81
107
|
Configuration for building documentation using sphinx.
|
|
82
108
|
"""
|
|
@@ -92,49 +118,72 @@ class SphinxConfig:
|
|
|
92
118
|
built documentation when the doc task is run with `--copy`.
|
|
93
119
|
"""
|
|
94
120
|
|
|
121
|
+
@classmethod
|
|
122
|
+
def create_kitchen_sink(cls) -> Self:
|
|
123
|
+
return cls()
|
|
124
|
+
|
|
95
125
|
|
|
96
126
|
@dataclass(kw_only=True)
|
|
97
|
-
class DocConfig:
|
|
127
|
+
class DocConfig(BaseConfig):
|
|
98
128
|
"""
|
|
99
129
|
Documentation tool configurations.
|
|
100
130
|
"""
|
|
101
131
|
|
|
102
|
-
mkinit: MkinitConfig | None =
|
|
132
|
+
mkinit: MkinitConfig | None = None
|
|
103
133
|
"""
|
|
104
|
-
Enables the `init` task
|
|
134
|
+
Enables the `init` task.
|
|
105
135
|
"""
|
|
106
136
|
|
|
107
137
|
sphinx: SphinxConfig | None = None
|
|
108
138
|
"""
|
|
109
|
-
Enables the `doc` task
|
|
139
|
+
Enables the `doc` task.
|
|
110
140
|
"""
|
|
111
141
|
|
|
142
|
+
@classmethod
|
|
143
|
+
def create_kitchen_sink(cls) -> Self:
|
|
144
|
+
"""
|
|
145
|
+
Enables mkinit; sphinx is left disabled since it needs project-specific
|
|
146
|
+
settings.
|
|
147
|
+
"""
|
|
148
|
+
return cls(mkinit=MkinitConfig.create_kitchen_sink())
|
|
149
|
+
|
|
112
150
|
|
|
113
151
|
@dataclass(kw_only=True)
|
|
114
|
-
class AnalysisConfig:
|
|
152
|
+
class AnalysisConfig(BaseConfig):
|
|
115
153
|
"""
|
|
116
154
|
Static analysis configuration.
|
|
117
155
|
"""
|
|
118
156
|
|
|
119
|
-
mypy: MypyConfig | None =
|
|
120
|
-
pyright:
|
|
157
|
+
mypy: MypyConfig | None = None
|
|
158
|
+
pyright: PyrightConfig | None = None
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def create_kitchen_sink(cls) -> Self:
|
|
162
|
+
return cls(
|
|
163
|
+
mypy=MypyConfig.create_kitchen_sink(),
|
|
164
|
+
pyright=PyrightConfig.create_kitchen_sink(),
|
|
165
|
+
)
|
|
121
166
|
|
|
122
167
|
|
|
123
168
|
@dataclass(kw_only=True)
|
|
124
|
-
class PublishConfig:
|
|
169
|
+
class PublishConfig(BaseConfig):
|
|
125
170
|
"""
|
|
126
171
|
Configuration for building and publishing via uv.
|
|
127
172
|
"""
|
|
128
173
|
|
|
129
|
-
out_dir: str =
|
|
174
|
+
out_dir: str | None = None
|
|
130
175
|
"""
|
|
131
|
-
Directory for build artifacts
|
|
132
|
-
never published.
|
|
176
|
+
Directory for build artifacts, defaulting to uv's `dist`; cleaned before each build
|
|
177
|
+
so stale artifacts are never published.
|
|
133
178
|
"""
|
|
134
179
|
|
|
180
|
+
@classmethod
|
|
181
|
+
def create_kitchen_sink(cls) -> Self:
|
|
182
|
+
return cls(out_dir=str(_paths.UV_PATH))
|
|
183
|
+
|
|
135
184
|
|
|
136
185
|
@dataclass(kw_only=True)
|
|
137
|
-
class SkillConfig:
|
|
186
|
+
class SkillConfig(BaseConfig):
|
|
138
187
|
"""
|
|
139
188
|
Agent skill integration: a `pyprojkit-python` skill in the
|
|
140
189
|
[Agent Skills](https://agentskills.io) format, generated from the project's
|
|
@@ -148,16 +197,20 @@ class SkillConfig:
|
|
|
148
197
|
`<skills_dir>/pyprojkit-python/SKILL.md`.
|
|
149
198
|
"""
|
|
150
199
|
|
|
200
|
+
@classmethod
|
|
201
|
+
def create_kitchen_sink(cls) -> Self:
|
|
202
|
+
return cls()
|
|
203
|
+
|
|
151
204
|
|
|
152
205
|
@dataclass(kw_only=True)
|
|
153
|
-
class ToolsConfig:
|
|
206
|
+
class ToolsConfig(BaseConfig):
|
|
154
207
|
"""
|
|
155
208
|
Development tool configurations, grouped by broad tool category.
|
|
156
209
|
|
|
157
210
|
Every category is opt-in: `None` (the default) means the tool is neither managed nor
|
|
158
|
-
given a task. For a pre-canned set of everything, see `
|
|
159
|
-
to share a configuration across
|
|
160
|
-
global.
|
|
211
|
+
given a task. For a pre-canned set of everything, see `create_kitchen_sink()` (also
|
|
212
|
+
available as `create_kitchen_sink_tools()`); to share a configuration across
|
|
213
|
+
projects, define your own factory function or global.
|
|
161
214
|
"""
|
|
162
215
|
|
|
163
216
|
workflow_tool: Literal["uv", "poetry"] | None = None
|
|
@@ -179,6 +232,26 @@ class ToolsConfig:
|
|
|
179
232
|
sync.
|
|
180
233
|
"""
|
|
181
234
|
|
|
235
|
+
@classmethod
|
|
236
|
+
def create_kitchen_sink(cls) -> Self:
|
|
237
|
+
"""
|
|
238
|
+
Enables every tool category, each with its opinionated settings: uv as the
|
|
239
|
+
workflow tool, formatting, testing, doit, nox, mkinit, static analysis,
|
|
240
|
+
publishing and the agent skill. Sphinx is left disabled since it needs
|
|
241
|
+
project-specific settings.
|
|
242
|
+
"""
|
|
243
|
+
return cls(
|
|
244
|
+
workflow_tool="uv",
|
|
245
|
+
formatting=FormattingConfig.create_kitchen_sink(),
|
|
246
|
+
test=TestConfig.create_kitchen_sink(),
|
|
247
|
+
doit=DoitConfig.create_kitchen_sink(),
|
|
248
|
+
nox=NoxConfig.create_kitchen_sink(),
|
|
249
|
+
doc=DocConfig.create_kitchen_sink(),
|
|
250
|
+
analysis=AnalysisConfig.create_kitchen_sink(),
|
|
251
|
+
publish=PublishConfig.create_kitchen_sink(),
|
|
252
|
+
skill=SkillConfig.create_kitchen_sink(),
|
|
253
|
+
)
|
|
254
|
+
|
|
182
255
|
|
|
183
256
|
@dataclass(kw_only=True)
|
|
184
257
|
class ProjectConfig:
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configurations for all supported tools.
|
|
3
|
+
|
|
4
|
+
Formatters are tools which additionally run as part of the `format` task. Every field
|
|
5
|
+
defaults to `None` (unset); each tool's opinionated settings are provided by its
|
|
6
|
+
`create_kitchen_sink()`.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Self
|
|
13
|
+
|
|
14
|
+
from .. import _paths
|
|
15
|
+
from .base import BaseFormatterConfig, BaseToolConfig
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from .project import ProjectConfig
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"AutoflakeConfig",
|
|
22
|
+
"IsortConfig",
|
|
23
|
+
"BlackConfig",
|
|
24
|
+
"DocfmtConfig",
|
|
25
|
+
"TomlSortConfig",
|
|
26
|
+
"PytestConfig",
|
|
27
|
+
"CoverageRunConfig",
|
|
28
|
+
"CoverageReportConfig",
|
|
29
|
+
"DoitConfig",
|
|
30
|
+
"NoxConfig",
|
|
31
|
+
"MypyConfig",
|
|
32
|
+
"PyrightConfig",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# --- formatters (run order defined by FormattingConfig) ---
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(kw_only=True)
|
|
40
|
+
class AutoflakeConfig(BaseFormatterConfig):
|
|
41
|
+
table_path: ClassVar[str] = "tool.autoflake"
|
|
42
|
+
|
|
43
|
+
in_place: bool | None = None
|
|
44
|
+
recursive: bool | None = None
|
|
45
|
+
remove_all_unused_imports: bool | None = field(
|
|
46
|
+
default=None, metadata={"toml": "remove-all-unused-imports"}
|
|
47
|
+
)
|
|
48
|
+
remove_unused_variables: bool | None = field(
|
|
49
|
+
default=None, metadata={"toml": "remove-unused-variables"}
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def create_kitchen_sink(cls) -> Self:
|
|
54
|
+
return cls(
|
|
55
|
+
in_place=True,
|
|
56
|
+
recursive=True,
|
|
57
|
+
remove_all_unused_imports=True,
|
|
58
|
+
remove_unused_variables=True,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
62
|
+
return ["autoflake"] + py_paths
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(kw_only=True)
|
|
66
|
+
class IsortConfig(BaseFormatterConfig):
|
|
67
|
+
table_path: ClassVar[str] = "tool.isort"
|
|
68
|
+
|
|
69
|
+
profile: str | None = None
|
|
70
|
+
quiet: bool | None = None
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def create_kitchen_sink(cls) -> Self:
|
|
74
|
+
return cls(profile="black", quiet=True)
|
|
75
|
+
|
|
76
|
+
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
77
|
+
return ["isort"] + py_paths
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass(kw_only=True)
|
|
81
|
+
class BlackConfig(BaseFormatterConfig):
|
|
82
|
+
table_path: ClassVar[str] = "tool.black"
|
|
83
|
+
|
|
84
|
+
quiet: bool | None = None
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def create_kitchen_sink(cls) -> Self:
|
|
88
|
+
return cls(quiet=True)
|
|
89
|
+
|
|
90
|
+
def extra_toml(self, project: ProjectConfig) -> dict[str, Any]:
|
|
91
|
+
versions = project.pinned_versions
|
|
92
|
+
if versions is None:
|
|
93
|
+
return {}
|
|
94
|
+
return {"target-version": [f"py{maj}{min}" for maj, min in versions.versions]}
|
|
95
|
+
|
|
96
|
+
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
97
|
+
return ["black"] + py_paths
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass(kw_only=True)
|
|
101
|
+
class DocfmtConfig(BaseFormatterConfig):
|
|
102
|
+
table_path: ClassVar[str] = "tool.docfmt"
|
|
103
|
+
|
|
104
|
+
# docfmt returns 0 when it writes changes in-place; 1 means "would change"
|
|
105
|
+
# in check mode and 2 is an error, so only 0 is expected here
|
|
106
|
+
expect_rc: ClassVar[frozenset[int]] = frozenset({0})
|
|
107
|
+
|
|
108
|
+
# line length is left unset: docfmt picks it up from `[tool.black]`
|
|
109
|
+
in_place: bool | None = field(default=None, metadata={"toml": "in-place"})
|
|
110
|
+
recursive: bool | None = None
|
|
111
|
+
summary_on_own_line: bool | None = field(
|
|
112
|
+
default=None, metadata={"toml": "summary-on-own-line"}
|
|
113
|
+
)
|
|
114
|
+
force_reflow: bool | None = field(default=None, metadata={"toml": "force-reflow"})
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
def create_kitchen_sink(cls) -> Self:
|
|
118
|
+
return cls(
|
|
119
|
+
in_place=True, recursive=True, summary_on_own_line=True, force_reflow=True
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
123
|
+
return ["docfmt"] + py_paths
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@dataclass(kw_only=True)
|
|
127
|
+
class TomlSortConfig(BaseFormatterConfig):
|
|
128
|
+
table_path: ClassVar[str] = "tool.tomlsort"
|
|
129
|
+
|
|
130
|
+
sort_first: tuple[str, ...] | None = None
|
|
131
|
+
sort_table_keys: bool | None = None
|
|
132
|
+
|
|
133
|
+
# the toml-sort CLI and library defaults disagree; when unset, the sync engine's
|
|
134
|
+
# normalization falls back to the CLI default so it agrees with the format task
|
|
135
|
+
spaces_before_inline_comment: int | None = None
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def create_kitchen_sink(cls) -> Self:
|
|
139
|
+
return cls(
|
|
140
|
+
sort_first=("project", "dependency-groups", "build-system"),
|
|
141
|
+
sort_table_keys=True,
|
|
142
|
+
spaces_before_inline_comment=2,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
146
|
+
return ["toml-sort", "-i"] + toml_paths
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# --- non-formatter tools ---
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@dataclass(kw_only=True)
|
|
153
|
+
class PytestConfig(BaseToolConfig):
|
|
154
|
+
table_path: ClassVar[str] = "tool.pytest.ini_options"
|
|
155
|
+
|
|
156
|
+
addopts: str | None = None
|
|
157
|
+
cache_dir: str | None = None
|
|
158
|
+
testpaths: str | None = None
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def create_kitchen_sink(cls) -> Self:
|
|
162
|
+
return cls(
|
|
163
|
+
addopts="--import-mode=importlib -s -v -rA",
|
|
164
|
+
cache_dir=str(_paths.PYTEST_CACHE_PATH),
|
|
165
|
+
testpaths="test",
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@dataclass(kw_only=True)
|
|
170
|
+
class CoverageRunConfig(BaseToolConfig):
|
|
171
|
+
table_path: ClassVar[str] = "tool.coverage.run"
|
|
172
|
+
|
|
173
|
+
data_file: str | None = None
|
|
174
|
+
|
|
175
|
+
@classmethod
|
|
176
|
+
def create_kitchen_sink(cls) -> Self:
|
|
177
|
+
return cls(data_file=str(_paths.COVERAGE_DATA_PATH))
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@dataclass(kw_only=True)
|
|
181
|
+
class CoverageReportConfig(BaseToolConfig):
|
|
182
|
+
table_path: ClassVar[str] = "tool.coverage.report"
|
|
183
|
+
|
|
184
|
+
exclude_lines: tuple[str, ...] | None = None
|
|
185
|
+
|
|
186
|
+
@classmethod
|
|
187
|
+
def create_kitchen_sink(cls) -> Self:
|
|
188
|
+
return cls(exclude_lines=("if TYPE_CHECKING:", "\\.\\.\\.$"))
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
@dataclass(kw_only=True)
|
|
192
|
+
class DoitConfig(BaseToolConfig):
|
|
193
|
+
table_path: ClassVar[str] = "tool.doit"
|
|
194
|
+
|
|
195
|
+
dep_file: str | None = None
|
|
196
|
+
verbosity: int | None = None
|
|
197
|
+
|
|
198
|
+
@classmethod
|
|
199
|
+
def create_kitchen_sink(cls) -> Self:
|
|
200
|
+
return cls(dep_file=str(_paths.DOIT_DB_PATH), verbosity=2)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@dataclass(kw_only=True)
|
|
204
|
+
class NoxConfig(BaseToolConfig):
|
|
205
|
+
table_path: ClassVar[str] = "tool.nox"
|
|
206
|
+
|
|
207
|
+
default_venv_backend: str | None = None
|
|
208
|
+
envdir: str | None = None
|
|
209
|
+
|
|
210
|
+
@classmethod
|
|
211
|
+
def create_kitchen_sink(cls) -> Self:
|
|
212
|
+
return cls(default_venv_backend="uv", envdir=str(_paths.NOX_ENVDIR_PATH))
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@dataclass(kw_only=True)
|
|
216
|
+
class MypyConfig(BaseToolConfig):
|
|
217
|
+
table_path: ClassVar[str] = "tool.mypy"
|
|
218
|
+
|
|
219
|
+
ignore_missing_imports: bool | None = None
|
|
220
|
+
check_untyped_defs: bool | None = None
|
|
221
|
+
|
|
222
|
+
@classmethod
|
|
223
|
+
def create_kitchen_sink(cls) -> Self:
|
|
224
|
+
return cls(ignore_missing_imports=True, check_untyped_defs=True)
|
|
225
|
+
|
|
226
|
+
def extra_toml(self, project: ProjectConfig) -> dict[str, Any]:
|
|
227
|
+
versions = project.pinned_versions
|
|
228
|
+
if versions is None:
|
|
229
|
+
return {}
|
|
230
|
+
maj, min = versions.versions[0]
|
|
231
|
+
return {"python_version": f"{maj}.{min}"}
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
@dataclass(kw_only=True)
|
|
235
|
+
class PyrightConfig(BaseToolConfig):
|
|
236
|
+
table_path: ClassVar[str] = "tool.pyright"
|
|
237
|
+
|
|
238
|
+
@classmethod
|
|
239
|
+
def create_kitchen_sink(cls) -> Self:
|
|
240
|
+
return cls()
|
|
241
|
+
|
|
242
|
+
def extra_toml(self, project: ProjectConfig) -> dict[str, Any]:
|
|
243
|
+
versions = project.pinned_versions
|
|
244
|
+
if versions is None:
|
|
245
|
+
return {}
|
|
246
|
+
maj, min = versions.versions[0]
|
|
247
|
+
return {"pythonVersion": f"{maj}.{min}"}
|
|
@@ -45,7 +45,7 @@ class NoxFactory:
|
|
|
45
45
|
):
|
|
46
46
|
self._config = config or load_config(root)
|
|
47
47
|
self._registered = set()
|
|
48
|
-
if nox_config := self._config.tools.nox:
|
|
48
|
+
if (nox_config := self._config.tools.nox) and nox_config.envdir is not None:
|
|
49
49
|
nox.options.envdir = nox_config.envdir
|
|
50
50
|
|
|
51
51
|
def create_test_session(self, *, group: str = "dev") -> Callable[[Session], None]:
|
|
@@ -45,7 +45,7 @@ from tomlkit import TOMLDocument
|
|
|
45
45
|
from tomlkit.items import AoT, Null, Table
|
|
46
46
|
|
|
47
47
|
from ._run import run
|
|
48
|
-
from .config.base import ConfigError
|
|
48
|
+
from .config.base import BaseToolConfig, ConfigError
|
|
49
49
|
from .config.project import ProjectConfig, SkillConfig
|
|
50
50
|
from .config.tools import TomlSortConfig
|
|
51
51
|
from .skill import SKILL_NAME, render_skill
|
|
@@ -70,25 +70,21 @@ def compute_managed_fields(config: ProjectConfig) -> dict[str, dict[str, Any]]:
|
|
|
70
70
|
"""
|
|
71
71
|
Compute all managed fields, keyed by dotted table path then key.
|
|
72
72
|
"""
|
|
73
|
-
|
|
73
|
+
tool_configs: list[BaseToolConfig] = []
|
|
74
74
|
tools = config.tools
|
|
75
75
|
|
|
76
76
|
if tools.formatting:
|
|
77
|
-
|
|
78
|
-
tables[formatter.table_path] = formatter.to_toml(config)
|
|
77
|
+
tool_configs += tools.formatting.formatters
|
|
79
78
|
|
|
80
79
|
if test := tools.test:
|
|
81
|
-
|
|
82
|
-
tables[test_tool.table_path] = test_tool.to_toml(config)
|
|
80
|
+
tool_configs += [test.pytest, test.coverage_run, test.coverage_report]
|
|
83
81
|
|
|
84
|
-
for
|
|
85
|
-
if runner:
|
|
86
|
-
tables[runner.table_path] = runner.to_toml(config)
|
|
82
|
+
tool_configs += [t for t in (tools.doit, tools.nox) if t]
|
|
87
83
|
|
|
88
|
-
if
|
|
89
|
-
|
|
84
|
+
if analysis := tools.analysis:
|
|
85
|
+
tool_configs += [t for t in (analysis.mypy, analysis.pyright) if t]
|
|
90
86
|
|
|
91
|
-
return
|
|
87
|
+
return {t.table_path: t.to_toml(config) for t in tool_configs}
|
|
92
88
|
|
|
93
89
|
|
|
94
90
|
def render(config: ProjectConfig, text: str) -> str:
|
|
@@ -347,7 +347,7 @@ class TaskFactory:
|
|
|
347
347
|
Create `publish` task which builds and publishes the package via uv.
|
|
348
348
|
"""
|
|
349
349
|
publish = self._require(self._config.tools.publish, "tools.publish")
|
|
350
|
-
out_dir = Path(publish.out_dir)
|
|
350
|
+
out_dir = Path(publish.out_dir or "dist")
|
|
351
351
|
|
|
352
352
|
def _publish():
|
|
353
353
|
artifacts = [str(p) for p in sorted(out_dir.iterdir())]
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Built-in tool configurations.
|
|
3
|
-
|
|
4
|
-
Configurations are plain `ToolsConfig` values: define your own factory function or
|
|
5
|
-
global in a module shared across projects, optionally building on
|
|
6
|
-
`create_kitchen_sink_tools()`:
|
|
7
|
-
|
|
8
|
-
```python
|
|
9
|
-
from dataclasses import replace
|
|
10
|
-
|
|
11
|
-
from pyprojkit import AnalysisConfig, ToolsConfig, create_kitchen_sink_tools
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def create_mycompany_tools() -> ToolsConfig:
|
|
15
|
-
return replace(create_kitchen_sink_tools(), analysis=AnalysisConfig())
|
|
16
|
-
```
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
from __future__ import annotations
|
|
20
|
-
|
|
21
|
-
from .project import (
|
|
22
|
-
AnalysisConfig,
|
|
23
|
-
DocConfig,
|
|
24
|
-
FormattingConfig,
|
|
25
|
-
PublishConfig,
|
|
26
|
-
SkillConfig,
|
|
27
|
-
TestConfig,
|
|
28
|
-
ToolsConfig,
|
|
29
|
-
)
|
|
30
|
-
from .tools import (
|
|
31
|
-
AutoflakeConfig,
|
|
32
|
-
BlackConfig,
|
|
33
|
-
DocfmtConfig,
|
|
34
|
-
DoitConfig,
|
|
35
|
-
IsortConfig,
|
|
36
|
-
NoxConfig,
|
|
37
|
-
TomlSortConfig,
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
__all__ = [
|
|
41
|
-
"create_kitchen_sink_tools",
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def create_kitchen_sink_tools() -> ToolsConfig:
|
|
46
|
-
"""
|
|
47
|
-
Get a new instance of the configuration which enables every tool: uv as the workflow
|
|
48
|
-
tool, formatting, testing, doit, nox, mkinit, static analysis, publishing and the
|
|
49
|
-
agent skill. Sphinx is left disabled since it needs project-specific settings.
|
|
50
|
-
"""
|
|
51
|
-
return ToolsConfig(
|
|
52
|
-
workflow_tool="uv",
|
|
53
|
-
formatting=FormattingConfig(
|
|
54
|
-
formatters=(
|
|
55
|
-
AutoflakeConfig(),
|
|
56
|
-
IsortConfig(),
|
|
57
|
-
DocfmtConfig(),
|
|
58
|
-
BlackConfig(),
|
|
59
|
-
TomlSortConfig(),
|
|
60
|
-
)
|
|
61
|
-
),
|
|
62
|
-
test=TestConfig(),
|
|
63
|
-
doit=DoitConfig(),
|
|
64
|
-
nox=NoxConfig(),
|
|
65
|
-
doc=DocConfig(),
|
|
66
|
-
analysis=AnalysisConfig(),
|
|
67
|
-
publish=PublishConfig(),
|
|
68
|
-
skill=SkillConfig(),
|
|
69
|
-
)
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Configurations for all supported tools.
|
|
3
|
-
|
|
4
|
-
Formatters are tools which additionally run as part of the `format` task.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from dataclasses import dataclass, field
|
|
10
|
-
from typing import TYPE_CHECKING, Any, ClassVar
|
|
11
|
-
|
|
12
|
-
from .. import _paths
|
|
13
|
-
from .base import BaseFormatterConfig, BaseToolConfig
|
|
14
|
-
|
|
15
|
-
if TYPE_CHECKING:
|
|
16
|
-
from .project import ProjectConfig
|
|
17
|
-
|
|
18
|
-
__all__ = [
|
|
19
|
-
"AutoflakeConfig",
|
|
20
|
-
"IsortConfig",
|
|
21
|
-
"BlackConfig",
|
|
22
|
-
"DocfmtConfig",
|
|
23
|
-
"TomlSortConfig",
|
|
24
|
-
"PytestConfig",
|
|
25
|
-
"CoverageRunConfig",
|
|
26
|
-
"CoverageReportConfig",
|
|
27
|
-
"DoitConfig",
|
|
28
|
-
"NoxConfig",
|
|
29
|
-
"MypyConfig",
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# --- formatters (run order defined by FormattingConfig) ---
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@dataclass(kw_only=True)
|
|
37
|
-
class AutoflakeConfig(BaseFormatterConfig):
|
|
38
|
-
table_path: ClassVar[str] = "tool.autoflake"
|
|
39
|
-
|
|
40
|
-
in_place: bool | None = True
|
|
41
|
-
recursive: bool | None = True
|
|
42
|
-
remove_all_unused_imports: bool | None = field(
|
|
43
|
-
default=True, metadata={"toml": "remove-all-unused-imports"}
|
|
44
|
-
)
|
|
45
|
-
remove_unused_variables: bool | None = field(
|
|
46
|
-
default=True, metadata={"toml": "remove-unused-variables"}
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
50
|
-
return ["autoflake"] + py_paths
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@dataclass(kw_only=True)
|
|
54
|
-
class IsortConfig(BaseFormatterConfig):
|
|
55
|
-
table_path: ClassVar[str] = "tool.isort"
|
|
56
|
-
|
|
57
|
-
profile: str | None = "black"
|
|
58
|
-
quiet: bool | None = True
|
|
59
|
-
|
|
60
|
-
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
61
|
-
return ["isort"] + py_paths
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@dataclass(kw_only=True)
|
|
65
|
-
class BlackConfig(BaseFormatterConfig):
|
|
66
|
-
table_path: ClassVar[str] = "tool.black"
|
|
67
|
-
|
|
68
|
-
quiet: bool | None = True
|
|
69
|
-
|
|
70
|
-
def extra_toml(self, project: ProjectConfig) -> dict[str, Any]:
|
|
71
|
-
versions = project.pinned_versions
|
|
72
|
-
if versions is None:
|
|
73
|
-
return {}
|
|
74
|
-
return {"target-version": [f"py{maj}{min}" for maj, min in versions.versions]}
|
|
75
|
-
|
|
76
|
-
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
77
|
-
return ["black"] + py_paths
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
@dataclass(kw_only=True)
|
|
81
|
-
class DocfmtConfig(BaseFormatterConfig):
|
|
82
|
-
table_path: ClassVar[str] = "tool.docfmt"
|
|
83
|
-
|
|
84
|
-
# docfmt returns 0 when it writes changes in-place; 1 means "would change"
|
|
85
|
-
# in check mode and 2 is an error, so only 0 is expected here
|
|
86
|
-
expect_rc: ClassVar[frozenset[int]] = frozenset({0})
|
|
87
|
-
|
|
88
|
-
# line length is left unset: docfmt picks it up from `[tool.black]`
|
|
89
|
-
in_place: bool | None = field(default=True, metadata={"toml": "in-place"})
|
|
90
|
-
recursive: bool | None = True
|
|
91
|
-
summary_on_own_line: bool | None = field(
|
|
92
|
-
default=True, metadata={"toml": "summary-on-own-line"}
|
|
93
|
-
)
|
|
94
|
-
force_reflow: bool | None = field(default=True, metadata={"toml": "force-reflow"})
|
|
95
|
-
|
|
96
|
-
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
97
|
-
return ["docfmt"] + py_paths
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
@dataclass(kw_only=True)
|
|
101
|
-
class TomlSortConfig(BaseFormatterConfig):
|
|
102
|
-
table_path: ClassVar[str] = "tool.tomlsort"
|
|
103
|
-
|
|
104
|
-
sort_first: tuple[str, ...] | None = (
|
|
105
|
-
"project",
|
|
106
|
-
"dependency-groups",
|
|
107
|
-
"build-system",
|
|
108
|
-
)
|
|
109
|
-
sort_table_keys: bool | None = True
|
|
110
|
-
|
|
111
|
-
# explicit since the toml-sort CLI and library defaults disagree; must be
|
|
112
|
-
# pinned so the sync engine's normalization and the format task agree
|
|
113
|
-
spaces_before_inline_comment: int | None = 2
|
|
114
|
-
|
|
115
|
-
def command(self, py_paths: list[str], toml_paths: list[str]) -> list[str]:
|
|
116
|
-
return ["toml-sort", "-i"] + toml_paths
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# --- non-formatter tools ---
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
@dataclass(kw_only=True)
|
|
123
|
-
class PytestConfig(BaseToolConfig):
|
|
124
|
-
table_path: ClassVar[str] = "tool.pytest.ini_options"
|
|
125
|
-
|
|
126
|
-
addopts: str | None = "--import-mode=importlib -s -v -rA"
|
|
127
|
-
cache_dir: str | None = str(_paths.PYTEST_CACHE_PATH)
|
|
128
|
-
testpaths: str | None = "test"
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
@dataclass(kw_only=True)
|
|
132
|
-
class CoverageRunConfig(BaseToolConfig):
|
|
133
|
-
table_path: ClassVar[str] = "tool.coverage.run"
|
|
134
|
-
|
|
135
|
-
data_file: str | None = str(_paths.COVERAGE_DATA_PATH)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
@dataclass(kw_only=True)
|
|
139
|
-
class CoverageReportConfig(BaseToolConfig):
|
|
140
|
-
table_path: ClassVar[str] = "tool.coverage.report"
|
|
141
|
-
|
|
142
|
-
exclude_lines: tuple[str, ...] | None = (
|
|
143
|
-
"if TYPE_CHECKING:",
|
|
144
|
-
"\\.\\.\\.$",
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
@dataclass(kw_only=True)
|
|
149
|
-
class DoitConfig(BaseToolConfig):
|
|
150
|
-
table_path: ClassVar[str] = "tool.doit"
|
|
151
|
-
|
|
152
|
-
dep_file: str | None = str(_paths.DOIT_DB_PATH)
|
|
153
|
-
verbosity: int | None = 2
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
@dataclass(kw_only=True)
|
|
157
|
-
class NoxConfig(BaseToolConfig):
|
|
158
|
-
table_path: ClassVar[str] = "tool.nox"
|
|
159
|
-
|
|
160
|
-
default_venv_backend: str | None = "uv"
|
|
161
|
-
envdir: str | None = str(_paths.NOX_ENVDIR_PATH)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
@dataclass(kw_only=True)
|
|
165
|
-
class MypyConfig(BaseToolConfig):
|
|
166
|
-
table_path: ClassVar[str] = "tool.mypy"
|
|
167
|
-
|
|
168
|
-
ignore_missing_imports: bool | None = True
|
|
169
|
-
|
|
170
|
-
def extra_toml(self, project: ProjectConfig) -> dict[str, Any]:
|
|
171
|
-
versions = project.pinned_versions
|
|
172
|
-
if versions is None:
|
|
173
|
-
return {}
|
|
174
|
-
maj, min = versions.versions[0]
|
|
175
|
-
return {"python_version": f"{maj}.{min}"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|