jaymd96-pants-baseline 0.1.2__py3-none-any.whl
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.
- jaymd96_pants_baseline-0.1.2.dist-info/METADATA +385 -0
- jaymd96_pants_baseline-0.1.2.dist-info/RECORD +25 -0
- jaymd96_pants_baseline-0.1.2.dist-info/WHEEL +4 -0
- jaymd96_pants_baseline-0.1.2.dist-info/licenses/LICENSE +190 -0
- pants_baseline/__about__.py +4 -0
- pants_baseline/__init__.py +17 -0
- pants_baseline/goals/__init__.py +11 -0
- pants_baseline/goals/audit.py +76 -0
- pants_baseline/goals/fmt.py +56 -0
- pants_baseline/goals/lint.py +59 -0
- pants_baseline/goals/test.py +53 -0
- pants_baseline/goals/typecheck.py +55 -0
- pants_baseline/register.py +46 -0
- pants_baseline/rules/__init__.py +11 -0
- pants_baseline/rules/audit_rules.py +78 -0
- pants_baseline/rules/fmt_rules.py +120 -0
- pants_baseline/rules/lint_rules.py +133 -0
- pants_baseline/rules/test_rules.py +149 -0
- pants_baseline/rules/typecheck_rules.py +144 -0
- pants_baseline/subsystems/__init__.py +13 -0
- pants_baseline/subsystems/baseline.py +74 -0
- pants_baseline/subsystems/ruff.py +90 -0
- pants_baseline/subsystems/ty.py +80 -0
- pants_baseline/subsystems/uv.py +66 -0
- pants_baseline/targets.py +138 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""Rules for pytest testing with coverage."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Iterable
|
|
7
|
+
|
|
8
|
+
from pants.core.goals.test import TestRequest, TestResult
|
|
9
|
+
from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
|
|
10
|
+
from pants.engine.process import FallibleProcessResult, Process
|
|
11
|
+
from pants.engine.rules import Get, collect_rules, rule
|
|
12
|
+
from pants.engine.target import FieldSet
|
|
13
|
+
from pants.engine.unions import UnionRule
|
|
14
|
+
from pants.util.logging import LogLevel
|
|
15
|
+
|
|
16
|
+
from pants_baseline.subsystems.baseline import BaselineSubsystem
|
|
17
|
+
from pants_baseline.targets import (
|
|
18
|
+
BaselineSourcesField,
|
|
19
|
+
BaselineTestSourcesField,
|
|
20
|
+
CoverageThresholdField,
|
|
21
|
+
SkipTestField,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class PytestFieldSet(FieldSet):
|
|
27
|
+
"""Field set for pytest testing."""
|
|
28
|
+
|
|
29
|
+
required_fields = (BaselineTestSourcesField,)
|
|
30
|
+
|
|
31
|
+
sources: BaselineSourcesField
|
|
32
|
+
test_sources: BaselineTestSourcesField
|
|
33
|
+
coverage_threshold: CoverageThresholdField
|
|
34
|
+
skip_test: SkipTestField
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class PytestTestRequest(TestRequest):
|
|
38
|
+
"""Request to run pytest tests."""
|
|
39
|
+
|
|
40
|
+
field_set_type = PytestFieldSet
|
|
41
|
+
tool_name = "pytest"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@rule(desc="Test with pytest", level=LogLevel.DEBUG)
|
|
45
|
+
async def run_pytest(
|
|
46
|
+
request: PytestTestRequest,
|
|
47
|
+
baseline_subsystem: BaselineSubsystem,
|
|
48
|
+
) -> TestResult:
|
|
49
|
+
"""Run pytest on test files with coverage."""
|
|
50
|
+
if not baseline_subsystem.enabled:
|
|
51
|
+
return TestResult(
|
|
52
|
+
exit_code=0,
|
|
53
|
+
stdout="",
|
|
54
|
+
stderr="",
|
|
55
|
+
stdout_digest=None,
|
|
56
|
+
stderr_digest=None,
|
|
57
|
+
address=None,
|
|
58
|
+
output_setting=None,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Filter out skipped targets
|
|
62
|
+
field_sets = [fs for fs in request.field_sets if not fs.skip_test.value]
|
|
63
|
+
|
|
64
|
+
if not field_sets:
|
|
65
|
+
return TestResult(
|
|
66
|
+
exit_code=0,
|
|
67
|
+
stdout="No targets to test",
|
|
68
|
+
stderr="",
|
|
69
|
+
stdout_digest=None,
|
|
70
|
+
stderr_digest=None,
|
|
71
|
+
address=None,
|
|
72
|
+
output_setting=None,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Get test source files
|
|
76
|
+
test_source_files_request = SourceFilesRequest(
|
|
77
|
+
sources_fields=[fs.test_sources for fs in field_sets],
|
|
78
|
+
for_sources_types=(BaselineTestSourcesField,),
|
|
79
|
+
)
|
|
80
|
+
test_sources = await Get(SourceFiles, {SourceFilesRequest: test_source_files_request})
|
|
81
|
+
|
|
82
|
+
# Get source files for coverage
|
|
83
|
+
source_files_request = SourceFilesRequest(
|
|
84
|
+
sources_fields=[fs.sources for fs in field_sets],
|
|
85
|
+
for_sources_types=(BaselineSourcesField,),
|
|
86
|
+
)
|
|
87
|
+
sources = await Get(SourceFiles, {SourceFilesRequest: source_files_request})
|
|
88
|
+
|
|
89
|
+
if not test_sources.files:
|
|
90
|
+
return TestResult(
|
|
91
|
+
exit_code=0,
|
|
92
|
+
stdout="No test files found",
|
|
93
|
+
stderr="",
|
|
94
|
+
stdout_digest=None,
|
|
95
|
+
stderr_digest=None,
|
|
96
|
+
address=None,
|
|
97
|
+
output_setting=None,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Get coverage threshold from first field set (or use default)
|
|
101
|
+
coverage_threshold = (
|
|
102
|
+
field_sets[0].coverage_threshold.value
|
|
103
|
+
if field_sets
|
|
104
|
+
else baseline_subsystem.coverage_threshold
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Build pytest command with coverage
|
|
108
|
+
src_root = ",".join(baseline_subsystem.src_roots)
|
|
109
|
+
|
|
110
|
+
argv = [
|
|
111
|
+
"pytest",
|
|
112
|
+
"-v",
|
|
113
|
+
"--strict-markers",
|
|
114
|
+
"--strict-config",
|
|
115
|
+
"-ra",
|
|
116
|
+
"--tb=short",
|
|
117
|
+
f"--cov={src_root}",
|
|
118
|
+
"--cov-report=term-missing",
|
|
119
|
+
f"--cov-fail-under={coverage_threshold}",
|
|
120
|
+
"--cov-branch",
|
|
121
|
+
*test_sources.files,
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
process = Process(
|
|
125
|
+
argv=argv,
|
|
126
|
+
input_digest=test_sources.snapshot.digest,
|
|
127
|
+
description=f"Run pytest on {len(test_sources.files)} test files",
|
|
128
|
+
level=LogLevel.DEBUG,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
result = await Get(FallibleProcessResult, {Process: process})
|
|
132
|
+
|
|
133
|
+
return TestResult(
|
|
134
|
+
exit_code=result.exit_code,
|
|
135
|
+
stdout=result.stdout.decode(),
|
|
136
|
+
stderr=result.stderr.decode(),
|
|
137
|
+
stdout_digest=None,
|
|
138
|
+
stderr_digest=None,
|
|
139
|
+
address=None,
|
|
140
|
+
output_setting=None,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def rules() -> Iterable:
|
|
145
|
+
"""Return all test rules."""
|
|
146
|
+
return [
|
|
147
|
+
*collect_rules(),
|
|
148
|
+
UnionRule(TestRequest, PytestTestRequest),
|
|
149
|
+
]
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Rules for ty type checking."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Iterable
|
|
7
|
+
|
|
8
|
+
from pants.core.goals.check import CheckRequest, CheckResult, CheckResults
|
|
9
|
+
from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
|
|
10
|
+
from pants.engine.process import FallibleProcessResult, Process
|
|
11
|
+
from pants.engine.rules import Get, collect_rules, rule
|
|
12
|
+
from pants.engine.target import FieldSet
|
|
13
|
+
from pants.engine.unions import UnionRule
|
|
14
|
+
from pants.util.logging import LogLevel
|
|
15
|
+
|
|
16
|
+
from pants_baseline.subsystems.baseline import BaselineSubsystem
|
|
17
|
+
from pants_baseline.subsystems.ty import TySubsystem
|
|
18
|
+
from pants_baseline.targets import BaselineSourcesField, SkipTypecheckField
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class TyFieldSet(FieldSet):
|
|
23
|
+
"""Field set for ty type checking."""
|
|
24
|
+
|
|
25
|
+
required_fields = (BaselineSourcesField,)
|
|
26
|
+
|
|
27
|
+
sources: BaselineSourcesField
|
|
28
|
+
skip_typecheck: SkipTypecheckField
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class TyCheckRequest(CheckRequest):
|
|
32
|
+
"""Request to run ty type checking."""
|
|
33
|
+
|
|
34
|
+
field_set_type = TyFieldSet
|
|
35
|
+
tool_name = "ty"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class TyCheckResult:
|
|
40
|
+
"""Result of running ty type check."""
|
|
41
|
+
|
|
42
|
+
exit_code: int
|
|
43
|
+
stdout: str
|
|
44
|
+
stderr: str
|
|
45
|
+
partition_description: str | None = None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@rule(desc="Type check with ty", level=LogLevel.DEBUG)
|
|
49
|
+
async def run_ty_check(
|
|
50
|
+
request: TyCheckRequest,
|
|
51
|
+
ty_subsystem: TySubsystem,
|
|
52
|
+
baseline_subsystem: BaselineSubsystem,
|
|
53
|
+
) -> CheckResults:
|
|
54
|
+
"""Run ty type checker on Python files."""
|
|
55
|
+
if not baseline_subsystem.enabled:
|
|
56
|
+
return CheckResults(
|
|
57
|
+
results=[
|
|
58
|
+
CheckResult(
|
|
59
|
+
exit_code=0,
|
|
60
|
+
stdout="",
|
|
61
|
+
stderr="",
|
|
62
|
+
partition_description=None,
|
|
63
|
+
)
|
|
64
|
+
],
|
|
65
|
+
checker_name="ty",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Filter out skipped targets
|
|
69
|
+
field_sets = [fs for fs in request.field_sets if not fs.skip_typecheck.value]
|
|
70
|
+
|
|
71
|
+
if not field_sets:
|
|
72
|
+
return CheckResults(
|
|
73
|
+
results=[
|
|
74
|
+
CheckResult(
|
|
75
|
+
exit_code=0,
|
|
76
|
+
stdout="No targets to type check",
|
|
77
|
+
stderr="",
|
|
78
|
+
partition_description=None,
|
|
79
|
+
)
|
|
80
|
+
],
|
|
81
|
+
checker_name="ty",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Get source files
|
|
85
|
+
source_files_request = SourceFilesRequest(
|
|
86
|
+
sources_fields=[fs.sources for fs in field_sets],
|
|
87
|
+
for_sources_types=(BaselineSourcesField,),
|
|
88
|
+
)
|
|
89
|
+
sources = await Get(SourceFiles, {SourceFilesRequest: source_files_request})
|
|
90
|
+
|
|
91
|
+
if not sources.files:
|
|
92
|
+
return CheckResults(
|
|
93
|
+
results=[
|
|
94
|
+
CheckResult(
|
|
95
|
+
exit_code=0,
|
|
96
|
+
stdout="No files to type check",
|
|
97
|
+
stderr="",
|
|
98
|
+
partition_description=None,
|
|
99
|
+
)
|
|
100
|
+
],
|
|
101
|
+
checker_name="ty",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Build ty command
|
|
105
|
+
strict_arg = ["--strict"] if ty_subsystem.strict else []
|
|
106
|
+
output_format_arg = [f"--output-format={ty_subsystem.output_format}"]
|
|
107
|
+
|
|
108
|
+
argv = [
|
|
109
|
+
"ty",
|
|
110
|
+
"check",
|
|
111
|
+
f"--python-version={baseline_subsystem.python_version}",
|
|
112
|
+
*strict_arg,
|
|
113
|
+
*output_format_arg,
|
|
114
|
+
*sources.files,
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
process = Process(
|
|
118
|
+
argv=argv,
|
|
119
|
+
input_digest=sources.snapshot.digest,
|
|
120
|
+
description=f"Run ty type check on {len(sources.files)} files",
|
|
121
|
+
level=LogLevel.DEBUG,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
result = await Get(FallibleProcessResult, {Process: process})
|
|
125
|
+
|
|
126
|
+
return CheckResults(
|
|
127
|
+
results=[
|
|
128
|
+
CheckResult(
|
|
129
|
+
exit_code=result.exit_code,
|
|
130
|
+
stdout=result.stdout.decode(),
|
|
131
|
+
stderr=result.stderr.decode(),
|
|
132
|
+
partition_description=None,
|
|
133
|
+
)
|
|
134
|
+
],
|
|
135
|
+
checker_name="ty",
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def rules() -> Iterable:
|
|
140
|
+
"""Return all type check rules."""
|
|
141
|
+
return [
|
|
142
|
+
*collect_rules(),
|
|
143
|
+
UnionRule(CheckRequest, TyCheckRequest),
|
|
144
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Subsystems for Python Baseline plugin configuration."""
|
|
2
|
+
|
|
3
|
+
from pants_baseline.subsystems.baseline import BaselineSubsystem
|
|
4
|
+
from pants_baseline.subsystems.ruff import RuffSubsystem
|
|
5
|
+
from pants_baseline.subsystems.ty import TySubsystem
|
|
6
|
+
from pants_baseline.subsystems.uv import UvSubsystem
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"BaselineSubsystem",
|
|
10
|
+
"RuffSubsystem",
|
|
11
|
+
"TySubsystem",
|
|
12
|
+
"UvSubsystem",
|
|
13
|
+
]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Main baseline subsystem for coordinating all quality tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pants.option.option_types import BoolOption, IntOption, StrListOption, StrOption
|
|
6
|
+
from pants.option.subsystem import Subsystem
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BaselineSubsystem(Subsystem):
|
|
10
|
+
"""Configuration for the Python Baseline quality framework.
|
|
11
|
+
|
|
12
|
+
This subsystem provides global configuration for all baseline tools
|
|
13
|
+
including Ruff, ty, pytest, and uv audit.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
options_scope = "python-baseline"
|
|
17
|
+
help = "Opinionated Python code quality baseline configuration."
|
|
18
|
+
|
|
19
|
+
# Global settings
|
|
20
|
+
enabled = BoolOption(
|
|
21
|
+
default=True,
|
|
22
|
+
help="Whether to enable the Python baseline checks globally.",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
python_version = StrOption(
|
|
26
|
+
default="3.11",
|
|
27
|
+
help="Target Python version for all tools (e.g., '3.11', '3.12').",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
line_length = IntOption(
|
|
31
|
+
default=120,
|
|
32
|
+
help="Maximum line length for formatting and linting.",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
src_roots = StrListOption(
|
|
36
|
+
default=["src"],
|
|
37
|
+
help="Source root directories for Python code.",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
test_roots = StrListOption(
|
|
41
|
+
default=["tests"],
|
|
42
|
+
help="Test root directories.",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
exclude_patterns = StrListOption(
|
|
46
|
+
default=[
|
|
47
|
+
".venv",
|
|
48
|
+
".git",
|
|
49
|
+
"__pycache__",
|
|
50
|
+
"dist",
|
|
51
|
+
"build",
|
|
52
|
+
".pytest_cache",
|
|
53
|
+
".ruff_cache",
|
|
54
|
+
"migrations",
|
|
55
|
+
],
|
|
56
|
+
help="Patterns to exclude from all baseline checks.",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Coverage threshold
|
|
60
|
+
coverage_threshold = IntOption(
|
|
61
|
+
default=80,
|
|
62
|
+
help="Minimum code coverage percentage required.",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Strictness level
|
|
66
|
+
strict_mode = BoolOption(
|
|
67
|
+
default=True,
|
|
68
|
+
help="Enable strict mode for all tools (more rigorous checks).",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def get_python_target_version(self) -> str:
|
|
72
|
+
"""Return Python version in format suitable for tools (e.g., 'py311')."""
|
|
73
|
+
version = self.python_version.replace(".", "")
|
|
74
|
+
return f"py{version}"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Ruff subsystem for linting and formatting configuration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pants.option.option_types import BoolOption, StrListOption, StrOption
|
|
6
|
+
from pants.option.subsystem import Subsystem
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RuffSubsystem(Subsystem):
|
|
10
|
+
"""Configuration for Ruff linting and formatting.
|
|
11
|
+
|
|
12
|
+
Ruff is an extremely fast Python linter and formatter, written in Rust.
|
|
13
|
+
It replaces Black, isort, Flake8, and many other tools in a single binary.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
options_scope = "baseline-ruff"
|
|
17
|
+
help = "Ruff linting and formatting configuration for baseline plugin."
|
|
18
|
+
|
|
19
|
+
version = StrOption(
|
|
20
|
+
default="0.2.0",
|
|
21
|
+
help="Version of Ruff to use.",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Linting configuration
|
|
25
|
+
select = StrListOption(
|
|
26
|
+
default=[
|
|
27
|
+
"E", # pycodestyle errors
|
|
28
|
+
"W", # pycodestyle warnings
|
|
29
|
+
"F", # pyflakes
|
|
30
|
+
"I", # isort
|
|
31
|
+
"N", # pep8-naming
|
|
32
|
+
"UP", # pyupgrade
|
|
33
|
+
"B", # flake8-bugbear
|
|
34
|
+
"C4", # flake8-comprehensions
|
|
35
|
+
"SIM", # flake8-simplify
|
|
36
|
+
"ASYNC", # flake8-async
|
|
37
|
+
"DTZ", # flake8-datetimez
|
|
38
|
+
"PIE", # flake8-pie
|
|
39
|
+
"RUF", # Ruff-specific rules
|
|
40
|
+
],
|
|
41
|
+
help="Rule codes to enable for linting.",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
ignore = StrListOption(
|
|
45
|
+
default=[
|
|
46
|
+
"E501", # line too long (handled by formatter)
|
|
47
|
+
"W292", # blank line at end of file
|
|
48
|
+
],
|
|
49
|
+
help="Rule codes to ignore.",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Formatting configuration
|
|
53
|
+
quote_style = StrOption(
|
|
54
|
+
default="double",
|
|
55
|
+
help="Quote style for formatting ('double' or 'single').",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
indent_style = StrOption(
|
|
59
|
+
default="space",
|
|
60
|
+
help="Indentation style ('space' or 'tab').",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Auto-fix
|
|
64
|
+
fix = BoolOption(
|
|
65
|
+
default=True,
|
|
66
|
+
help="Automatically fix auto-fixable issues.",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
unsafe_fixes = BoolOption(
|
|
70
|
+
default=False,
|
|
71
|
+
help="Allow unsafe fixes that may change code behavior.",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Per-file ignores (common patterns)
|
|
75
|
+
skip_tests_rules = StrListOption(
|
|
76
|
+
default=[
|
|
77
|
+
"F401", # unused imports OK in tests
|
|
78
|
+
"F811", # redefined function OK in tests
|
|
79
|
+
"S101", # assert OK in tests
|
|
80
|
+
],
|
|
81
|
+
help="Rules to skip in test files.",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
skip_init_rules = StrListOption(
|
|
85
|
+
default=[
|
|
86
|
+
"F401", # unused imports (exports)
|
|
87
|
+
"F403", # star imports OK for namespace
|
|
88
|
+
],
|
|
89
|
+
help="Rules to skip in __init__.py files.",
|
|
90
|
+
)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""ty subsystem for type checking configuration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pants.option.option_types import BoolOption, StrListOption, StrOption
|
|
6
|
+
from pants.option.subsystem import Subsystem
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TySubsystem(Subsystem):
|
|
10
|
+
"""Configuration for ty type checker.
|
|
11
|
+
|
|
12
|
+
ty is Astral's next-generation Python type checker, designed for
|
|
13
|
+
exceptional performance (10-60x faster than MyPy, 80x faster than
|
|
14
|
+
Pyright on incremental edits).
|
|
15
|
+
|
|
16
|
+
Features:
|
|
17
|
+
- LSP-first architecture for IDE integration
|
|
18
|
+
- Incremental checking optimized for real-time feedback
|
|
19
|
+
- First-class intersection types and reachability analysis
|
|
20
|
+
- Rust implementation with obsessive performance focus
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
options_scope = "baseline-ty"
|
|
24
|
+
help = "ty type checker configuration for baseline plugin (Astral's next-gen type checker)."
|
|
25
|
+
|
|
26
|
+
version = StrOption(
|
|
27
|
+
default="0.1.0",
|
|
28
|
+
help="Version of ty to use.",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Type checking mode
|
|
32
|
+
strict = BoolOption(
|
|
33
|
+
default=True,
|
|
34
|
+
help="Enable strict type checking mode.",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Error reporting
|
|
38
|
+
report_missing_imports = BoolOption(
|
|
39
|
+
default=True,
|
|
40
|
+
help="Report errors for missing imports.",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
report_unused_imports = BoolOption(
|
|
44
|
+
default=True,
|
|
45
|
+
help="Report errors for unused imports.",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
report_unused_variables = BoolOption(
|
|
49
|
+
default=True,
|
|
50
|
+
help="Report errors for unused variables.",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Include/exclude paths
|
|
54
|
+
include = StrListOption(
|
|
55
|
+
default=["src", "tests"],
|
|
56
|
+
help="Directories to include in type checking.",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
exclude = StrListOption(
|
|
60
|
+
default=[
|
|
61
|
+
".venv",
|
|
62
|
+
".git",
|
|
63
|
+
"__pycache__",
|
|
64
|
+
"dist",
|
|
65
|
+
"build",
|
|
66
|
+
],
|
|
67
|
+
help="Patterns to exclude from type checking.",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Type stub handling
|
|
71
|
+
stub_path = StrOption(
|
|
72
|
+
default="",
|
|
73
|
+
help="Path to custom type stubs directory.",
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Output format
|
|
77
|
+
output_format = StrOption(
|
|
78
|
+
default="text",
|
|
79
|
+
help="Output format for type errors ('text', 'json', 'github').",
|
|
80
|
+
)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""uv subsystem for dependency management and security auditing."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pants.option.option_types import BoolOption, StrListOption, StrOption
|
|
6
|
+
from pants.option.subsystem import Subsystem
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class UvSubsystem(Subsystem):
|
|
10
|
+
"""Configuration for uv dependency management and security auditing.
|
|
11
|
+
|
|
12
|
+
uv is Astral's ultra-fast Python package installer and resolver,
|
|
13
|
+
written in Rust. It's 10-100x faster than pip for dependency resolution.
|
|
14
|
+
|
|
15
|
+
This subsystem configures uv for:
|
|
16
|
+
- Dependency security auditing (vulnerability scanning)
|
|
17
|
+
- Lock file management
|
|
18
|
+
- Virtual environment management
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
options_scope = "baseline-uv"
|
|
22
|
+
help = "uv dependency management and security auditing configuration for baseline plugin."
|
|
23
|
+
|
|
24
|
+
version = StrOption(
|
|
25
|
+
default="0.5.0",
|
|
26
|
+
help="Version of uv to use.",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Security auditing
|
|
30
|
+
audit_enabled = BoolOption(
|
|
31
|
+
default=True,
|
|
32
|
+
help="Enable dependency security auditing.",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
audit_ignore_vulns = StrListOption(
|
|
36
|
+
default=[],
|
|
37
|
+
help="Vulnerability IDs to ignore (e.g., 'GHSA-xxxx-xxxx-xxxx').",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
audit_fail_on_warning = BoolOption(
|
|
41
|
+
default=False,
|
|
42
|
+
help="Fail the audit if any warnings are found (not just errors).",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Lock file settings
|
|
46
|
+
lock_file = StrOption(
|
|
47
|
+
default="uv.lock",
|
|
48
|
+
help="Path to the uv lock file.",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
require_lock = BoolOption(
|
|
52
|
+
default=True,
|
|
53
|
+
help="Require a lock file to exist for auditing.",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# Output format
|
|
57
|
+
output_format = StrOption(
|
|
58
|
+
default="text",
|
|
59
|
+
help="Output format for audit results ('text', 'json', 'github').",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Additional arguments
|
|
63
|
+
extra_args = StrListOption(
|
|
64
|
+
default=[],
|
|
65
|
+
help="Additional arguments to pass to uv commands.",
|
|
66
|
+
)
|