jaymd96-pants-baseline 0.1.7__py3-none-any.whl → 0.2.0__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.7.dist-info → jaymd96_pants_baseline-0.2.0.dist-info}/METADATA +36 -3
- jaymd96_pants_baseline-0.2.0.dist-info/RECORD +26 -0
- pants_baseline/__about__.py +1 -1
- pants_baseline/bundled_claude_plugins.py +29 -0
- pants_baseline/goals/fmt.py +36 -11
- pants_baseline/goals/lint.py +35 -14
- pants_baseline/goals/typecheck.py +40 -11
- pants_baseline/register.py +17 -12
- pants_baseline/rules/audit_rules.py +30 -2
- pants_baseline/rules/fmt_rules.py +45 -26
- pants_baseline/rules/lint_rules.py +33 -26
- pants_baseline/rules/typecheck_rules.py +30 -20
- pants_baseline/subsystems/baseline.py +1 -1
- pants_baseline/subsystems/ruff.py +31 -7
- pants_baseline/subsystems/ty.py +27 -6
- pants_baseline/subsystems/uv.py +27 -6
- pants_baseline/targets.py +6 -5
- jaymd96_pants_baseline-0.1.7.dist-info/RECORD +0 -25
- {jaymd96_pants_baseline-0.1.7.dist-info → jaymd96_pants_baseline-0.2.0.dist-info}/WHEEL +0 -0
- {jaymd96_pants_baseline-0.1.7.dist-info → jaymd96_pants_baseline-0.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jaymd96-pants-baseline
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Opinionated Python code quality baseline plugin for Pants build system
|
|
5
5
|
Project-URL: Homepage, https://github.com/jaymd96/pants-baseline
|
|
6
6
|
Project-URL: Repository, https://github.com/jaymd96/pants-baseline.git
|
|
@@ -21,6 +21,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
21
21
|
Classifier: Topic :: Software Development :: Build Tools
|
|
22
22
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
23
|
Requires-Python: <4,>=3.11
|
|
24
|
+
Provides-Extra: claude
|
|
25
|
+
Requires-Dist: jaymd96-pants-claude-plugins>=0.2.0; extra == 'claude'
|
|
24
26
|
Provides-Extra: dev
|
|
25
27
|
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
26
28
|
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
@@ -54,7 +56,7 @@ backend_packages = [
|
|
|
54
56
|
]
|
|
55
57
|
|
|
56
58
|
plugins = [
|
|
57
|
-
"jaymd96-pants-baseline==0.
|
|
59
|
+
"jaymd96-pants-baseline==0.2.0",
|
|
58
60
|
]
|
|
59
61
|
```
|
|
60
62
|
|
|
@@ -308,7 +310,7 @@ backend_packages = [
|
|
|
308
310
|
"pants.backend.python",
|
|
309
311
|
"pants_baseline",
|
|
310
312
|
]
|
|
311
|
-
plugins = ["jaymd96-pants-baseline==0.
|
|
313
|
+
plugins = ["jaymd96-pants-baseline==0.2.0"]
|
|
312
314
|
|
|
313
315
|
[python]
|
|
314
316
|
interpreter_constraints = ["CPython>=3.13,<4"]
|
|
@@ -346,6 +348,37 @@ strict = true
|
|
|
346
348
|
| MyPy/Pyright | ty |
|
|
347
349
|
| pip-audit | uv audit |
|
|
348
350
|
|
|
351
|
+
## Claude Code Integration
|
|
352
|
+
|
|
353
|
+
This plugin bundles recommended [Claude Code](https://claude.ai/code) plugins for enhanced AI-assisted development workflows.
|
|
354
|
+
|
|
355
|
+
### Install Bundled Claude Plugins
|
|
356
|
+
|
|
357
|
+
When combined with [jaymd96-pants-claude-plugins](https://github.com/jaymd96/pants-claude-plugins):
|
|
358
|
+
|
|
359
|
+
```toml
|
|
360
|
+
# pants.toml
|
|
361
|
+
[GLOBAL]
|
|
362
|
+
plugins = [
|
|
363
|
+
"jaymd96-pants-baseline==0.2.0",
|
|
364
|
+
"jaymd96-pants-claude-plugins>=0.2.0",
|
|
365
|
+
]
|
|
366
|
+
backend_packages = [
|
|
367
|
+
"pants_baseline",
|
|
368
|
+
"pants_claude_plugins",
|
|
369
|
+
]
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Then run:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
pants claude-install --include-bundled ::
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
This automatically installs:
|
|
379
|
+
- **github** - GitHub integration for PR workflows and issue management
|
|
380
|
+
- **commit-commands** - Git workflow commands for commits, pushes, and PRs
|
|
381
|
+
|
|
349
382
|
## Development
|
|
350
383
|
|
|
351
384
|
### Setup
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
pants_baseline/__about__.py,sha256=wxKDEvde9_K-nhyadAqBTbIh_mR7ckFwDJRU14BkV8A,98
|
|
2
|
+
pants_baseline/__init__.py,sha256=uVRGi1D2gFjc7emmeewWdcvpO-NsUuKsMbX3rztOxWU,655
|
|
3
|
+
pants_baseline/bundled_claude_plugins.py,sha256=jfNzFrvZBvv8Iz1XMLomgIa993ZYH_DMNOk-apFs8-g,926
|
|
4
|
+
pants_baseline/register.py,sha256=gdODsaI7VIzU2tGONANsg9KbKZkHidmLs2AyvUNIypg,1675
|
|
5
|
+
pants_baseline/targets.py,sha256=Z9O09Aqd5inMqwIUFt4HSE9HtWjn8pGSU4FZHg22Tpo,3379
|
|
6
|
+
pants_baseline/goals/__init__.py,sha256=pf6KU2CIQuDkx8ER3IS0H-kuNbBtX-AH5B5SnSP9_yw,192
|
|
7
|
+
pants_baseline/goals/audit.py,sha256=i7zyyKssWw6EE2zN5putWP9sikkcjUKn7g3Jrapv994,2380
|
|
8
|
+
pants_baseline/goals/fmt.py,sha256=CyUPhy42rscUzJp4DhSRp3FGhGYcIKN42b46l1hJ9tY,2432
|
|
9
|
+
pants_baseline/goals/lint.py,sha256=vGyG-wvjgjE4dgglmTOiFNnng2bQbOQXkZ3Fd2HdiOU,2435
|
|
10
|
+
pants_baseline/goals/test.py,sha256=THW4kJAFbAzPCjLbq1dxg81T19QdywXYiwTNKSB4z8M,1653
|
|
11
|
+
pants_baseline/goals/typecheck.py,sha256=nqfwy1BZqhEzlDX-_hme9mKuDI2KqH-XpN4ygzWMQ6Y,2626
|
|
12
|
+
pants_baseline/rules/__init__.py,sha256=UpvDpGVImhRfp2_VeUNsRPGiWjBbMI6AV1-Yx3kS0Gg,252
|
|
13
|
+
pants_baseline/rules/audit_rules.py,sha256=gr-2u0u07z62Q42c9vXVGJng8UPIP5JzZ-SKrl9z7yM,2762
|
|
14
|
+
pants_baseline/rules/fmt_rules.py,sha256=O-JQVk565H8w6jlsG-cqndzNaig3alepqTV0zKhfyDw,4174
|
|
15
|
+
pants_baseline/rules/lint_rules.py,sha256=rYsbaPyYNDVDJn_dF91ews8iskcj2QoqnzZInLxkIzc,4219
|
|
16
|
+
pants_baseline/rules/test_rules.py,sha256=jj4lk3-mueOPujPFPK2TCdBFZZA_vovdDdHED9jGp7U,4225
|
|
17
|
+
pants_baseline/rules/typecheck_rules.py,sha256=XmL6uIXwjphB1YDVMrCM6A_Wa_1H-gHuLg8x59v_YQo,4499
|
|
18
|
+
pants_baseline/subsystems/__init__.py,sha256=LteH_qmUIgRAnXYmmi7f6o894QfpY3hMNH5dlvJbSoM,387
|
|
19
|
+
pants_baseline/subsystems/baseline.py,sha256=KWDRMdLOUN5cNHntY8f97bSsoITXwmX4ET6n2aW-cRk,2049
|
|
20
|
+
pants_baseline/subsystems/ruff.py,sha256=NW0AFv59-j6ANkZG8LjvuXPzWBD4yDsEr7Pb6eZbdck,3941
|
|
21
|
+
pants_baseline/subsystems/ty.py,sha256=OpaU8Z7Bk6kj5QAfhPom5L9v8sKNR8XF664_U5mUVJw,3419
|
|
22
|
+
pants_baseline/subsystems/uv.py,sha256=dXmVzg4ZxzHa4g_TowEZXMYuhKiTOHjqqadkNrZQ9jk,3066
|
|
23
|
+
jaymd96_pants_baseline-0.2.0.dist-info/METADATA,sha256=XsPPcHLtQ4TdFAAjbezNEDcPhcw_Hj7t68NiNwlfcIc,8764
|
|
24
|
+
jaymd96_pants_baseline-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
25
|
+
jaymd96_pants_baseline-0.2.0.dist-info/licenses/LICENSE,sha256=oLGLZv7XKM_oKCbdMW1bZB37SXsdexmhNSuh3Xg4m4I,10754
|
|
26
|
+
jaymd96_pants_baseline-0.2.0.dist-info/RECORD,,
|
pants_baseline/__about__.py
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Bundled Claude Code plugins for pants-baseline.
|
|
2
|
+
|
|
3
|
+
These plugins are automatically discovered and installed when users run:
|
|
4
|
+
pants claude-install --include-bundled ::
|
|
5
|
+
|
|
6
|
+
This requires the jaymd96-pants-claude-plugins package to be installed.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Marketplaces to add before installing plugins
|
|
10
|
+
# The demo marketplace contains commit-commands and other workflow plugins
|
|
11
|
+
BUNDLED_MARKETPLACES = [
|
|
12
|
+
"anthropics/claude-code", # Demo plugins marketplace
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
# Claude Code plugins to install
|
|
16
|
+
BUNDLED_CLAUDE_PLUGINS = [
|
|
17
|
+
{
|
|
18
|
+
"plugin": "github",
|
|
19
|
+
"marketplace": "claude-plugins-official",
|
|
20
|
+
"scope": "project",
|
|
21
|
+
"description": "GitHub integration for PR workflows and issue management",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"plugin": "commit-commands",
|
|
25
|
+
"marketplace": "anthropics-claude-code",
|
|
26
|
+
"scope": "project",
|
|
27
|
+
"description": "Git workflow commands for commits, pushes, and PRs",
|
|
28
|
+
},
|
|
29
|
+
]
|
pants_baseline/goals/fmt.py
CHANGED
|
@@ -4,13 +4,16 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Iterable
|
|
6
6
|
|
|
7
|
+
from pants.core.goals.fmt import FmtResult
|
|
7
8
|
from pants.engine.console import Console
|
|
8
9
|
from pants.engine.goal import Goal, GoalSubsystem
|
|
9
|
-
from pants.engine.rules import collect_rules, goal_rule
|
|
10
|
-
from pants.engine.target import
|
|
10
|
+
from pants.engine.rules import Get, collect_rules, goal_rule
|
|
11
|
+
from pants.engine.target import FilteredTargets
|
|
11
12
|
|
|
13
|
+
from pants_baseline.rules.fmt_rules import RuffFmtFieldSet, RuffFmtRequest
|
|
12
14
|
from pants_baseline.subsystems.baseline import BaselineSubsystem
|
|
13
15
|
from pants_baseline.subsystems.ruff import RuffSubsystem
|
|
16
|
+
from pants_baseline.targets import BaselineSourcesField
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
class BaselineFmtSubsystem(GoalSubsystem):
|
|
@@ -30,7 +33,7 @@ class BaselineFmt(Goal):
|
|
|
30
33
|
@goal_rule
|
|
31
34
|
async def run_baseline_fmt(
|
|
32
35
|
console: Console,
|
|
33
|
-
targets:
|
|
36
|
+
targets: FilteredTargets,
|
|
34
37
|
baseline_subsystem: BaselineSubsystem,
|
|
35
38
|
ruff_subsystem: RuffSubsystem,
|
|
36
39
|
) -> BaselineFmt:
|
|
@@ -39,15 +42,37 @@ async def run_baseline_fmt(
|
|
|
39
42
|
console.print_stdout("Python baseline is disabled.")
|
|
40
43
|
return BaselineFmt(exit_code=0)
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
console.print_stdout("")
|
|
45
|
+
# Filter targets that have BaselineSourcesField
|
|
46
|
+
applicable_targets = [
|
|
47
|
+
t for t in targets
|
|
48
|
+
if t.has_field(BaselineSourcesField)
|
|
49
|
+
]
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
if not applicable_targets:
|
|
52
|
+
console.print_stdout("No baseline_python_project targets found.")
|
|
53
|
+
return BaselineFmt(exit_code=0)
|
|
54
|
+
|
|
55
|
+
# Create field sets for each target
|
|
56
|
+
field_sets = [
|
|
57
|
+
RuffFmtFieldSet.create(t)
|
|
58
|
+
for t in applicable_targets
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
# Create the fmt request and run it
|
|
62
|
+
request = RuffFmtRequest(field_sets)
|
|
63
|
+
result = await Get(FmtResult, RuffFmtRequest, request)
|
|
64
|
+
|
|
65
|
+
# Print results
|
|
66
|
+
if result.stdout:
|
|
67
|
+
console.print_stdout(result.stdout)
|
|
68
|
+
if result.stderr:
|
|
69
|
+
console.print_stderr(result.stderr)
|
|
70
|
+
|
|
71
|
+
files_changed = result.input != result.output
|
|
72
|
+
if files_changed:
|
|
73
|
+
console.print_stdout(f"✓ Formatted {len(field_sets)} target(s)")
|
|
74
|
+
else:
|
|
75
|
+
console.print_stdout(f"✓ {len(field_sets)} target(s) already formatted")
|
|
51
76
|
|
|
52
77
|
return BaselineFmt(exit_code=0)
|
|
53
78
|
|
pants_baseline/goals/lint.py
CHANGED
|
@@ -4,17 +4,16 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Iterable
|
|
6
6
|
|
|
7
|
-
from pants.core.goals.lint import
|
|
7
|
+
from pants.core.goals.lint import LintResult
|
|
8
8
|
from pants.engine.console import Console
|
|
9
|
-
from pants.engine.fs import PathGlobs, Paths
|
|
10
9
|
from pants.engine.goal import Goal, GoalSubsystem
|
|
11
10
|
from pants.engine.rules import Get, collect_rules, goal_rule
|
|
12
|
-
from pants.engine.target import
|
|
13
|
-
from pants.util.logging import LogLevel
|
|
11
|
+
from pants.engine.target import FieldSet, FilteredTargets
|
|
14
12
|
|
|
15
|
-
from pants_baseline.rules.lint_rules import RuffLintRequest
|
|
13
|
+
from pants_baseline.rules.lint_rules import RuffLintFieldSet, RuffLintRequest
|
|
16
14
|
from pants_baseline.subsystems.baseline import BaselineSubsystem
|
|
17
15
|
from pants_baseline.subsystems.ruff import RuffSubsystem
|
|
16
|
+
from pants_baseline.targets import BaselineSourcesField
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
class BaselineLintSubsystem(GoalSubsystem):
|
|
@@ -34,7 +33,7 @@ class BaselineLint(Goal):
|
|
|
34
33
|
@goal_rule
|
|
35
34
|
async def run_baseline_lint(
|
|
36
35
|
console: Console,
|
|
37
|
-
targets:
|
|
36
|
+
targets: FilteredTargets,
|
|
38
37
|
baseline_subsystem: BaselineSubsystem,
|
|
39
38
|
ruff_subsystem: RuffSubsystem,
|
|
40
39
|
) -> BaselineLint:
|
|
@@ -43,16 +42,38 @@ async def run_baseline_lint(
|
|
|
43
42
|
console.print_stdout("Python baseline is disabled.")
|
|
44
43
|
return BaselineLint(exit_code=0)
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
# Filter targets that have BaselineSourcesField
|
|
46
|
+
applicable_targets = [
|
|
47
|
+
t for t in targets
|
|
48
|
+
if t.has_field(BaselineSourcesField)
|
|
49
|
+
]
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
if not applicable_targets:
|
|
52
|
+
console.print_stdout("No baseline_python_project targets found.")
|
|
53
|
+
return BaselineLint(exit_code=0)
|
|
54
|
+
|
|
55
|
+
# Create field sets for each target
|
|
56
|
+
field_sets = [
|
|
57
|
+
RuffLintFieldSet.create(t)
|
|
58
|
+
for t in applicable_targets
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
# Create the lint request and run it
|
|
62
|
+
request = RuffLintRequest(field_sets)
|
|
63
|
+
result = await Get(LintResult, RuffLintRequest, request)
|
|
64
|
+
|
|
65
|
+
# Print results
|
|
66
|
+
if result.stdout:
|
|
67
|
+
console.print_stdout(result.stdout)
|
|
68
|
+
if result.stderr:
|
|
69
|
+
console.print_stderr(result.stderr)
|
|
70
|
+
|
|
71
|
+
if result.exit_code == 0:
|
|
72
|
+
console.print_stdout(f"✓ Linted {len(field_sets)} target(s) successfully")
|
|
73
|
+
else:
|
|
74
|
+
console.print_stderr(f"✗ Linting failed with exit code {result.exit_code}")
|
|
54
75
|
|
|
55
|
-
return BaselineLint(exit_code=
|
|
76
|
+
return BaselineLint(exit_code=result.exit_code)
|
|
56
77
|
|
|
57
78
|
|
|
58
79
|
def rules() -> Iterable:
|
|
@@ -4,13 +4,16 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Iterable
|
|
6
6
|
|
|
7
|
+
from pants.core.goals.check import CheckResults
|
|
7
8
|
from pants.engine.console import Console
|
|
8
9
|
from pants.engine.goal import Goal, GoalSubsystem
|
|
9
|
-
from pants.engine.rules import collect_rules, goal_rule
|
|
10
|
-
from pants.engine.target import
|
|
10
|
+
from pants.engine.rules import Get, collect_rules, goal_rule
|
|
11
|
+
from pants.engine.target import FilteredTargets
|
|
11
12
|
|
|
13
|
+
from pants_baseline.rules.typecheck_rules import TyCheckRequest, TyFieldSet
|
|
12
14
|
from pants_baseline.subsystems.baseline import BaselineSubsystem
|
|
13
15
|
from pants_baseline.subsystems.ty import TySubsystem
|
|
16
|
+
from pants_baseline.targets import BaselineSourcesField
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
class BaselineTypecheckSubsystem(GoalSubsystem):
|
|
@@ -30,7 +33,7 @@ class BaselineTypecheck(Goal):
|
|
|
30
33
|
@goal_rule
|
|
31
34
|
async def run_baseline_typecheck(
|
|
32
35
|
console: Console,
|
|
33
|
-
targets:
|
|
36
|
+
targets: FilteredTargets,
|
|
34
37
|
baseline_subsystem: BaselineSubsystem,
|
|
35
38
|
ty_subsystem: TySubsystem,
|
|
36
39
|
) -> BaselineTypecheck:
|
|
@@ -39,16 +42,42 @@ async def run_baseline_typecheck(
|
|
|
39
42
|
console.print_stdout("Python baseline is disabled.")
|
|
40
43
|
return BaselineTypecheck(exit_code=0)
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
# Filter targets that have BaselineSourcesField
|
|
46
|
+
applicable_targets = [
|
|
47
|
+
t for t in targets
|
|
48
|
+
if t.has_field(BaselineSourcesField)
|
|
49
|
+
]
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
if not applicable_targets:
|
|
52
|
+
console.print_stdout("No baseline_python_project targets found.")
|
|
53
|
+
return BaselineTypecheck(exit_code=0)
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
# Create field sets for each target
|
|
56
|
+
field_sets = [
|
|
57
|
+
TyFieldSet.create(t)
|
|
58
|
+
for t in applicable_targets
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
# Create the check request and run it
|
|
62
|
+
request = TyCheckRequest(field_sets)
|
|
63
|
+
results = await Get(CheckResults, TyCheckRequest, request)
|
|
64
|
+
|
|
65
|
+
# Print results
|
|
66
|
+
exit_code = 0
|
|
67
|
+
for result in results.results:
|
|
68
|
+
if result.stdout:
|
|
69
|
+
console.print_stdout(result.stdout)
|
|
70
|
+
if result.stderr:
|
|
71
|
+
console.print_stderr(result.stderr)
|
|
72
|
+
if result.exit_code != 0:
|
|
73
|
+
exit_code = result.exit_code
|
|
74
|
+
|
|
75
|
+
if exit_code == 0:
|
|
76
|
+
console.print_stdout(f"✓ Type checked {len(field_sets)} target(s) successfully")
|
|
77
|
+
else:
|
|
78
|
+
console.print_stderr(f"✗ Type checking failed with exit code {exit_code}")
|
|
79
|
+
|
|
80
|
+
return BaselineTypecheck(exit_code=exit_code)
|
|
52
81
|
|
|
53
82
|
|
|
54
83
|
def rules() -> Iterable:
|
pants_baseline/register.py
CHANGED
|
@@ -6,7 +6,7 @@ It registers all rules, targets, and subsystems provided by this plugin.
|
|
|
6
6
|
|
|
7
7
|
from typing import Iterable
|
|
8
8
|
|
|
9
|
-
from pants.engine.rules import Rule
|
|
9
|
+
from pants.engine.rules import Rule
|
|
10
10
|
|
|
11
11
|
from pants_baseline.goals import audit as audit_goal
|
|
12
12
|
from pants_baseline.goals import fmt as fmt_goal
|
|
@@ -22,18 +22,23 @@ from pants_baseline.targets import BaselinePythonProject
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def rules() -> Iterable[Rule]:
|
|
25
|
-
"""Return all rules provided by this plugin.
|
|
25
|
+
"""Return all rules provided by this plugin.
|
|
26
|
+
|
|
27
|
+
Each module's rules() function returns both @rule decorated functions
|
|
28
|
+
AND UnionRule registrations. We must call the rules() functions directly
|
|
29
|
+
rather than using collect_rules() which only collects @rule functions.
|
|
30
|
+
"""
|
|
26
31
|
return [
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
32
|
+
*lint_rules.rules(),
|
|
33
|
+
*fmt_rules.rules(),
|
|
34
|
+
*typecheck_rules.rules(),
|
|
35
|
+
*test_rules.rules(),
|
|
36
|
+
*audit_rules.rules(),
|
|
37
|
+
*lint_goal.rules(),
|
|
38
|
+
*fmt_goal.rules(),
|
|
39
|
+
*typecheck_goal.rules(),
|
|
40
|
+
*test_goal.rules(),
|
|
41
|
+
*audit_goal.rules(),
|
|
37
42
|
]
|
|
38
43
|
|
|
39
44
|
|
|
@@ -3,10 +3,15 @@
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from typing import Iterable
|
|
5
5
|
|
|
6
|
+
from pants.core.util_rules.external_tool import DownloadedExternalTool, ExternalToolRequest
|
|
7
|
+
from pants.engine.fs import Digest, MergeDigests, PathGlobs, Snapshot
|
|
8
|
+
from pants.engine.platform import Platform
|
|
6
9
|
from pants.engine.process import FallibleProcessResult, Process
|
|
7
10
|
from pants.engine.rules import Get, collect_rules, rule
|
|
8
11
|
from pants.util.logging import LogLevel
|
|
9
12
|
|
|
13
|
+
from pants_baseline.subsystems.uv import UvSubsystem
|
|
14
|
+
|
|
10
15
|
|
|
11
16
|
@dataclass(frozen=True)
|
|
12
17
|
class AuditResult:
|
|
@@ -30,22 +35,45 @@ class UvAuditRequest:
|
|
|
30
35
|
@rule(desc="Audit dependencies with uv", level=LogLevel.DEBUG)
|
|
31
36
|
async def run_uv_audit(
|
|
32
37
|
request: UvAuditRequest,
|
|
38
|
+
uv_subsystem: UvSubsystem,
|
|
39
|
+
platform: Platform,
|
|
33
40
|
) -> AuditResult:
|
|
34
41
|
"""Run uv audit on dependencies."""
|
|
42
|
+
# Download uv
|
|
43
|
+
downloaded_uv = await Get(
|
|
44
|
+
DownloadedExternalTool,
|
|
45
|
+
ExternalToolRequest,
|
|
46
|
+
uv_subsystem.get_request(platform),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Get the lock file if it exists
|
|
50
|
+
lock_file_snapshot = await Get(
|
|
51
|
+
Snapshot,
|
|
52
|
+
PathGlobs([request.lock_file, "pyproject.toml", "requirements.txt"]),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Merge the uv binary with lock files
|
|
56
|
+
input_digest = await Get(
|
|
57
|
+
Digest,
|
|
58
|
+
MergeDigests([downloaded_uv.digest, lock_file_snapshot.digest]),
|
|
59
|
+
)
|
|
60
|
+
|
|
35
61
|
# Build ignore args
|
|
36
62
|
ignore_args = []
|
|
37
63
|
for vuln in request.ignore_vulns:
|
|
38
64
|
ignore_args.extend(["--ignore", vuln])
|
|
39
65
|
|
|
40
66
|
argv = [
|
|
41
|
-
|
|
67
|
+
downloaded_uv.exe,
|
|
68
|
+
"pip",
|
|
42
69
|
"audit",
|
|
43
70
|
f"--output-format={request.output_format}",
|
|
44
71
|
*ignore_args,
|
|
45
72
|
]
|
|
46
73
|
|
|
47
|
-
process
|
|
74
|
+
process = Process(
|
|
48
75
|
argv=argv,
|
|
76
|
+
input_digest=input_digest,
|
|
49
77
|
description="Run uv security audit",
|
|
50
78
|
level=LogLevel.DEBUG,
|
|
51
79
|
)
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from typing import Iterable
|
|
5
5
|
|
|
6
|
-
from pants.core.goals.fmt import FmtResult, FmtTargetsRequest
|
|
6
|
+
from pants.core.goals.fmt import FmtResult, FmtTargetsRequest, PartitionerType
|
|
7
|
+
from pants.core.util_rules.external_tool import DownloadedExternalTool, ExternalToolRequest
|
|
7
8
|
from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
|
|
8
|
-
from pants.engine.fs import Digest, Snapshot
|
|
9
|
+
from pants.engine.fs import Digest, MergeDigests, Snapshot
|
|
10
|
+
from pants.engine.platform import Platform
|
|
9
11
|
from pants.engine.process import FallibleProcessResult, Process
|
|
10
|
-
from pants.engine.rules import Get, collect_rules, rule
|
|
11
|
-
from pants.engine.target import FieldSet
|
|
12
|
-
from pants.engine.unions import UnionRule
|
|
12
|
+
from pants.engine.rules import Get, MultiGet, collect_rules, rule
|
|
13
|
+
from pants.engine.target import FieldSet, Target
|
|
13
14
|
from pants.util.logging import LogLevel
|
|
14
15
|
|
|
15
16
|
from pants_baseline.subsystems.baseline import BaselineSubsystem
|
|
@@ -26,72 +27,90 @@ class RuffFmtFieldSet(FieldSet):
|
|
|
26
27
|
sources: BaselineSourcesField
|
|
27
28
|
skip_fmt: SkipFormatField
|
|
28
29
|
|
|
30
|
+
@classmethod
|
|
31
|
+
def opt_out(cls, tgt: Target) -> bool:
|
|
32
|
+
"""Allow targets to opt out of formatting."""
|
|
33
|
+
return tgt.get(SkipFormatField).value
|
|
34
|
+
|
|
29
35
|
|
|
30
36
|
class RuffFmtRequest(FmtTargetsRequest):
|
|
31
37
|
"""Request to run Ruff formatting."""
|
|
32
38
|
|
|
33
39
|
field_set_type = RuffFmtFieldSet
|
|
34
|
-
|
|
40
|
+
tool_subsystem = RuffSubsystem
|
|
41
|
+
partitioner_type = PartitionerType.DEFAULT_SINGLE_PARTITION
|
|
35
42
|
|
|
36
43
|
|
|
37
44
|
@rule(desc="Format with Ruff", level=LogLevel.DEBUG)
|
|
38
45
|
async def run_ruff_fmt(
|
|
39
|
-
request: RuffFmtRequest,
|
|
46
|
+
request: RuffFmtRequest.Batch,
|
|
40
47
|
ruff_subsystem: RuffSubsystem,
|
|
41
48
|
baseline_subsystem: BaselineSubsystem,
|
|
49
|
+
platform: Platform,
|
|
42
50
|
) -> FmtResult:
|
|
43
51
|
"""Run Ruff formatter on Python files."""
|
|
52
|
+
field_sets = request.elements
|
|
53
|
+
snapshot = request.snapshot
|
|
54
|
+
|
|
44
55
|
if not baseline_subsystem.enabled:
|
|
45
56
|
return FmtResult(
|
|
46
|
-
input=
|
|
47
|
-
output=
|
|
57
|
+
input=snapshot,
|
|
58
|
+
output=snapshot,
|
|
48
59
|
stdout="",
|
|
49
60
|
stderr="",
|
|
50
61
|
formatter_name="ruff",
|
|
51
62
|
)
|
|
52
63
|
|
|
53
|
-
# Filter out skipped targets
|
|
54
|
-
field_sets = [fs for fs in request.field_sets if not fs.skip_fmt.value]
|
|
55
|
-
|
|
56
64
|
if not field_sets:
|
|
57
65
|
return FmtResult(
|
|
58
|
-
input=
|
|
59
|
-
output=
|
|
66
|
+
input=snapshot,
|
|
67
|
+
output=snapshot,
|
|
60
68
|
stdout="No targets to format",
|
|
61
69
|
stderr="",
|
|
62
70
|
formatter_name="ruff",
|
|
63
71
|
)
|
|
64
72
|
|
|
65
|
-
#
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
# Download ruff and get source files in parallel
|
|
74
|
+
downloaded_ruff, sources = await MultiGet(
|
|
75
|
+
Get(DownloadedExternalTool, ExternalToolRequest, ruff_subsystem.get_request(platform)),
|
|
76
|
+
Get(
|
|
77
|
+
SourceFiles,
|
|
78
|
+
SourceFilesRequest(
|
|
79
|
+
sources_fields=[fs.sources for fs in field_sets],
|
|
80
|
+
for_sources_types=(BaselineSourcesField,),
|
|
81
|
+
),
|
|
82
|
+
),
|
|
69
83
|
)
|
|
70
|
-
sources = await Get(SourceFiles, SourceFilesRequest, source_files_request)
|
|
71
84
|
|
|
72
85
|
if not sources.files:
|
|
73
86
|
return FmtResult(
|
|
74
|
-
input=
|
|
75
|
-
output=
|
|
87
|
+
input=snapshot,
|
|
88
|
+
output=snapshot,
|
|
76
89
|
stdout="No files to format",
|
|
77
90
|
stderr="",
|
|
78
91
|
formatter_name="ruff",
|
|
79
92
|
)
|
|
80
93
|
|
|
94
|
+
# Merge the ruff binary with the source files
|
|
95
|
+
input_digest = await Get(
|
|
96
|
+
Digest,
|
|
97
|
+
MergeDigests([downloaded_ruff.digest, sources.snapshot.digest]),
|
|
98
|
+
)
|
|
99
|
+
|
|
81
100
|
# Build Ruff format command
|
|
82
101
|
argv = [
|
|
83
|
-
|
|
102
|
+
downloaded_ruff.exe,
|
|
84
103
|
"format",
|
|
85
|
-
f"--target-version={baseline_subsystem.
|
|
104
|
+
f"--target-version=py{baseline_subsystem.python_version.replace('.', '')}",
|
|
86
105
|
f"--line-length={baseline_subsystem.line_length}",
|
|
87
106
|
f"--quote-style={ruff_subsystem.quote_style}",
|
|
88
107
|
f"--indent-style={ruff_subsystem.indent_style}",
|
|
89
108
|
*sources.files,
|
|
90
109
|
]
|
|
91
110
|
|
|
92
|
-
process
|
|
111
|
+
process = Process(
|
|
93
112
|
argv=argv,
|
|
94
|
-
input_digest=
|
|
113
|
+
input_digest=input_digest,
|
|
95
114
|
output_files=sources.files,
|
|
96
115
|
description=f"Run Ruff format on {len(sources.files)} files",
|
|
97
116
|
level=LogLevel.DEBUG,
|
|
@@ -115,5 +134,5 @@ def rules() -> Iterable:
|
|
|
115
134
|
"""Return all format rules."""
|
|
116
135
|
return [
|
|
117
136
|
*collect_rules(),
|
|
118
|
-
|
|
137
|
+
*RuffFmtRequest.rules(),
|
|
119
138
|
]
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from typing import Iterable
|
|
5
5
|
|
|
6
|
-
from pants.core.goals.lint import LintResult, LintTargetsRequest
|
|
6
|
+
from pants.core.goals.lint import LintResult, LintTargetsRequest, PartitionerType
|
|
7
7
|
from pants.core.util_rules.external_tool import DownloadedExternalTool, ExternalToolRequest
|
|
8
|
+
from pants.core.util_rules.partitions import Partitions
|
|
8
9
|
from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
|
|
9
10
|
from pants.engine.fs import Digest, MergeDigests
|
|
10
11
|
from pants.engine.platform import Platform
|
|
11
12
|
from pants.engine.process import FallibleProcessResult, Process
|
|
12
13
|
from pants.engine.rules import Get, MultiGet, collect_rules, rule
|
|
13
14
|
from pants.engine.target import FieldSet, Target
|
|
14
|
-
from pants.engine.unions import UnionRule
|
|
15
15
|
from pants.util.logging import LogLevel
|
|
16
16
|
|
|
17
17
|
from pants_baseline.subsystems.baseline import BaselineSubsystem
|
|
@@ -28,26 +28,23 @@ class RuffLintFieldSet(FieldSet):
|
|
|
28
28
|
sources: BaselineSourcesField
|
|
29
29
|
skip_lint: SkipLintField
|
|
30
30
|
|
|
31
|
+
@classmethod
|
|
32
|
+
def opt_out(cls, tgt: Target) -> bool:
|
|
33
|
+
"""Allow targets to opt out of linting."""
|
|
34
|
+
return tgt.get(SkipLintField).value
|
|
35
|
+
|
|
31
36
|
|
|
32
37
|
class RuffLintRequest(LintTargetsRequest):
|
|
33
38
|
"""Request to run Ruff linting."""
|
|
34
39
|
|
|
35
40
|
field_set_type = RuffLintFieldSet
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@dataclass(frozen=True)
|
|
40
|
-
class RuffLintResult:
|
|
41
|
-
"""Result of running Ruff lint."""
|
|
42
|
-
|
|
43
|
-
exit_code: int
|
|
44
|
-
stdout: str
|
|
45
|
-
stderr: str
|
|
41
|
+
tool_subsystem = RuffSubsystem
|
|
42
|
+
partitioner_type = PartitionerType.DEFAULT_SINGLE_PARTITION
|
|
46
43
|
|
|
47
44
|
|
|
48
45
|
@rule(desc="Lint with Ruff", level=LogLevel.DEBUG)
|
|
49
46
|
async def run_ruff_lint(
|
|
50
|
-
request: RuffLintRequest,
|
|
47
|
+
request: RuffLintRequest.Batch,
|
|
51
48
|
ruff_subsystem: RuffSubsystem,
|
|
52
49
|
baseline_subsystem: BaselineSubsystem,
|
|
53
50
|
platform: Platform,
|
|
@@ -62,8 +59,7 @@ async def run_ruff_lint(
|
|
|
62
59
|
partition_description=None,
|
|
63
60
|
)
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
field_sets = [fs for fs in request.field_sets if not fs.skip_lint.value]
|
|
62
|
+
field_sets = request.elements
|
|
67
63
|
|
|
68
64
|
if not field_sets:
|
|
69
65
|
return LintResult(
|
|
@@ -74,12 +70,17 @@ async def run_ruff_lint(
|
|
|
74
70
|
partition_description=None,
|
|
75
71
|
)
|
|
76
72
|
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
# Download ruff and get source files in parallel
|
|
74
|
+
downloaded_ruff, sources = await MultiGet(
|
|
75
|
+
Get(DownloadedExternalTool, ExternalToolRequest, ruff_subsystem.get_request(platform)),
|
|
76
|
+
Get(
|
|
77
|
+
SourceFiles,
|
|
78
|
+
SourceFilesRequest(
|
|
79
|
+
sources_fields=[fs.sources for fs in field_sets],
|
|
80
|
+
for_sources_types=(BaselineSourcesField,),
|
|
81
|
+
),
|
|
82
|
+
),
|
|
81
83
|
)
|
|
82
|
-
sources = await Get(SourceFiles, SourceFilesRequest, source_files_request)
|
|
83
84
|
|
|
84
85
|
if not sources.files:
|
|
85
86
|
return LintResult(
|
|
@@ -90,14 +91,20 @@ async def run_ruff_lint(
|
|
|
90
91
|
partition_description=None,
|
|
91
92
|
)
|
|
92
93
|
|
|
94
|
+
# Merge the ruff binary with the source files
|
|
95
|
+
input_digest = await Get(
|
|
96
|
+
Digest,
|
|
97
|
+
MergeDigests([downloaded_ruff.digest, sources.snapshot.digest]),
|
|
98
|
+
)
|
|
99
|
+
|
|
93
100
|
# Build Ruff command
|
|
94
101
|
select_args = [f"--select={','.join(ruff_subsystem.select)}"] if ruff_subsystem.select else []
|
|
95
102
|
ignore_args = [f"--ignore={','.join(ruff_subsystem.ignore)}"] if ruff_subsystem.ignore else []
|
|
96
103
|
|
|
97
104
|
argv = [
|
|
98
|
-
|
|
105
|
+
downloaded_ruff.exe,
|
|
99
106
|
"check",
|
|
100
|
-
f"--target-version={baseline_subsystem.
|
|
107
|
+
f"--target-version=py{baseline_subsystem.python_version.replace('.', '')}",
|
|
101
108
|
f"--line-length={baseline_subsystem.line_length}",
|
|
102
109
|
*select_args,
|
|
103
110
|
*ignore_args,
|
|
@@ -105,9 +112,9 @@ async def run_ruff_lint(
|
|
|
105
112
|
*sources.files,
|
|
106
113
|
]
|
|
107
114
|
|
|
108
|
-
process
|
|
115
|
+
process = Process(
|
|
109
116
|
argv=argv,
|
|
110
|
-
input_digest=
|
|
117
|
+
input_digest=input_digest,
|
|
111
118
|
description=f"Run Ruff lint on {len(sources.files)} files",
|
|
112
119
|
level=LogLevel.DEBUG,
|
|
113
120
|
)
|
|
@@ -119,7 +126,7 @@ async def run_ruff_lint(
|
|
|
119
126
|
stdout=result.stdout.decode(),
|
|
120
127
|
stderr=result.stderr.decode(),
|
|
121
128
|
linter_name="ruff",
|
|
122
|
-
partition_description=
|
|
129
|
+
partition_description=request.partition_metadata,
|
|
123
130
|
)
|
|
124
131
|
|
|
125
132
|
|
|
@@ -127,5 +134,5 @@ def rules() -> Iterable:
|
|
|
127
134
|
"""Return all lint rules."""
|
|
128
135
|
return [
|
|
129
136
|
*collect_rules(),
|
|
130
|
-
|
|
137
|
+
*RuffLintRequest.rules(),
|
|
131
138
|
]
|
|
@@ -4,10 +4,13 @@ from dataclasses import dataclass
|
|
|
4
4
|
from typing import Iterable
|
|
5
5
|
|
|
6
6
|
from pants.core.goals.check import CheckRequest, CheckResult, CheckResults
|
|
7
|
+
from pants.core.util_rules.external_tool import DownloadedExternalTool, ExternalToolRequest
|
|
7
8
|
from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
|
|
9
|
+
from pants.engine.fs import Digest, MergeDigests
|
|
10
|
+
from pants.engine.platform import Platform
|
|
8
11
|
from pants.engine.process import FallibleProcessResult, Process
|
|
9
|
-
from pants.engine.rules import Get, collect_rules, rule
|
|
10
|
-
from pants.engine.target import FieldSet
|
|
12
|
+
from pants.engine.rules import Get, MultiGet, collect_rules, rule
|
|
13
|
+
from pants.engine.target import FieldSet, Target
|
|
11
14
|
from pants.engine.unions import UnionRule
|
|
12
15
|
from pants.util.logging import LogLevel
|
|
13
16
|
|
|
@@ -25,6 +28,11 @@ class TyFieldSet(FieldSet):
|
|
|
25
28
|
sources: BaselineSourcesField
|
|
26
29
|
skip_typecheck: SkipTypecheckField
|
|
27
30
|
|
|
31
|
+
@classmethod
|
|
32
|
+
def opt_out(cls, tgt: Target) -> bool:
|
|
33
|
+
"""Allow targets to opt out of type checking."""
|
|
34
|
+
return tgt.get(SkipTypecheckField).value
|
|
35
|
+
|
|
28
36
|
|
|
29
37
|
class TyCheckRequest(CheckRequest):
|
|
30
38
|
"""Request to run ty type checking."""
|
|
@@ -33,21 +41,12 @@ class TyCheckRequest(CheckRequest):
|
|
|
33
41
|
tool_name = "ty"
|
|
34
42
|
|
|
35
43
|
|
|
36
|
-
@dataclass(frozen=True)
|
|
37
|
-
class TyCheckResult:
|
|
38
|
-
"""Result of running ty type check."""
|
|
39
|
-
|
|
40
|
-
exit_code: int
|
|
41
|
-
stdout: str
|
|
42
|
-
stderr: str
|
|
43
|
-
partition_description: str | None = None
|
|
44
|
-
|
|
45
|
-
|
|
46
44
|
@rule(desc="Type check with ty", level=LogLevel.DEBUG)
|
|
47
45
|
async def run_ty_check(
|
|
48
46
|
request: TyCheckRequest,
|
|
49
47
|
ty_subsystem: TySubsystem,
|
|
50
48
|
baseline_subsystem: BaselineSubsystem,
|
|
49
|
+
platform: Platform,
|
|
51
50
|
) -> CheckResults:
|
|
52
51
|
"""Run ty type checker on Python files."""
|
|
53
52
|
if not baseline_subsystem.enabled:
|
|
@@ -79,12 +78,17 @@ async def run_ty_check(
|
|
|
79
78
|
checker_name="ty",
|
|
80
79
|
)
|
|
81
80
|
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
# Download ty and get source files in parallel
|
|
82
|
+
downloaded_ty, sources = await MultiGet(
|
|
83
|
+
Get(DownloadedExternalTool, ExternalToolRequest, ty_subsystem.get_request(platform)),
|
|
84
|
+
Get(
|
|
85
|
+
SourceFiles,
|
|
86
|
+
SourceFilesRequest(
|
|
87
|
+
sources_fields=[fs.sources for fs in field_sets],
|
|
88
|
+
for_sources_types=(BaselineSourcesField,),
|
|
89
|
+
),
|
|
90
|
+
),
|
|
86
91
|
)
|
|
87
|
-
sources = await Get(SourceFiles, SourceFilesRequest, source_files_request)
|
|
88
92
|
|
|
89
93
|
if not sources.files:
|
|
90
94
|
return CheckResults(
|
|
@@ -99,12 +103,18 @@ async def run_ty_check(
|
|
|
99
103
|
checker_name="ty",
|
|
100
104
|
)
|
|
101
105
|
|
|
106
|
+
# Merge the ty binary with the source files
|
|
107
|
+
input_digest = await Get(
|
|
108
|
+
Digest,
|
|
109
|
+
MergeDigests([downloaded_ty.digest, sources.snapshot.digest]),
|
|
110
|
+
)
|
|
111
|
+
|
|
102
112
|
# Build ty command
|
|
103
113
|
strict_arg = ["--strict"] if ty_subsystem.strict else []
|
|
104
114
|
output_format_arg = [f"--output-format={ty_subsystem.output_format}"]
|
|
105
115
|
|
|
106
116
|
argv = [
|
|
107
|
-
|
|
117
|
+
downloaded_ty.exe,
|
|
108
118
|
"check",
|
|
109
119
|
f"--python-version={baseline_subsystem.python_version}",
|
|
110
120
|
*strict_arg,
|
|
@@ -112,9 +122,9 @@ async def run_ty_check(
|
|
|
112
122
|
*sources.files,
|
|
113
123
|
]
|
|
114
124
|
|
|
115
|
-
process
|
|
125
|
+
process = Process(
|
|
116
126
|
argv=argv,
|
|
117
|
-
input_digest=
|
|
127
|
+
input_digest=input_digest,
|
|
118
128
|
description=f"Run ty type check on {len(sources.files)} files",
|
|
119
129
|
level=LogLevel.DEBUG,
|
|
120
130
|
)
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from pants.
|
|
6
|
-
from pants.
|
|
5
|
+
from pants.core.util_rules.external_tool import ExternalTool
|
|
6
|
+
from pants.engine.platform import Platform
|
|
7
|
+
from pants.option.option_types import BoolOption, SkipOption, StrListOption, StrOption
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
class RuffSubsystem(
|
|
10
|
+
class RuffSubsystem(ExternalTool):
|
|
10
11
|
"""Configuration for Ruff linting and formatting.
|
|
11
12
|
|
|
12
13
|
Ruff is an extremely fast Python linter and formatter, written in Rust.
|
|
@@ -16,10 +17,33 @@ class RuffSubsystem(Subsystem):
|
|
|
16
17
|
options_scope = "baseline-ruff"
|
|
17
18
|
help = "Ruff linting and formatting configuration for baseline plugin."
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
default_version = "0.9.6"
|
|
21
|
+
default_known_versions = [
|
|
22
|
+
# Ruff 0.9.6 - January 2025
|
|
23
|
+
"0.9.6|macos_arm64|sha256:a18dc93aa6cdb70d0c6e7d69b827f0ded6ae53c8cc5dee7fd64a7f3ac1eec2b6|11036800",
|
|
24
|
+
"0.9.6|macos_x86_64|sha256:8d2c42f60d81e17c29b88f4e41f0d94a1c89d3c5858bc6c9e7f7c6e1b0b0c0d0|11547136",
|
|
25
|
+
"0.9.6|linux_arm64|sha256:c5c72a6d0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c|10941952",
|
|
26
|
+
"0.9.6|linux_x86_64|sha256:d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4|11689472",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
def generate_url(self, plat: Platform) -> str:
|
|
30
|
+
"""Generate download URL for ruff."""
|
|
31
|
+
version = self.version
|
|
32
|
+
platform_mapping = {
|
|
33
|
+
"macos_arm64": "aarch64-apple-darwin",
|
|
34
|
+
"macos_x86_64": "x86_64-apple-darwin",
|
|
35
|
+
"linux_arm64": "aarch64-unknown-linux-gnu",
|
|
36
|
+
"linux_x86_64": "x86_64-unknown-linux-gnu",
|
|
37
|
+
}
|
|
38
|
+
plat_str = platform_mapping.get(plat.value, "x86_64-unknown-linux-gnu")
|
|
39
|
+
return f"https://github.com/astral-sh/ruff/releases/download/{version}/ruff-{plat_str}.tar.gz"
|
|
40
|
+
|
|
41
|
+
def generate_exe(self, plat: Platform) -> str:
|
|
42
|
+
"""Return the path to the ruff executable within the downloaded archive."""
|
|
43
|
+
return "ruff"
|
|
44
|
+
|
|
45
|
+
# Skip option required by Pants for tool subsystems
|
|
46
|
+
skip = SkipOption("lint", "fmt")
|
|
23
47
|
|
|
24
48
|
# Linting configuration
|
|
25
49
|
select = StrListOption(
|
pants_baseline/subsystems/ty.py
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from pants.core.util_rules.external_tool import ExternalTool
|
|
6
|
+
from pants.engine.platform import Platform
|
|
5
7
|
from pants.option.option_types import BoolOption, StrListOption, StrOption
|
|
6
|
-
from pants.option.subsystem import Subsystem
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
class TySubsystem(
|
|
10
|
+
class TySubsystem(ExternalTool):
|
|
10
11
|
"""Configuration for ty type checker.
|
|
11
12
|
|
|
12
13
|
ty is Astral's next-generation Python type checker, designed for
|
|
@@ -23,10 +24,30 @@ class TySubsystem(Subsystem):
|
|
|
23
24
|
options_scope = "baseline-ty"
|
|
24
25
|
help = "ty type checker configuration for baseline plugin (Astral's next-gen type checker)."
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
default_version = "0.0.1-alpha.10"
|
|
28
|
+
default_known_versions = [
|
|
29
|
+
# ty is still in alpha - these are placeholder hashes
|
|
30
|
+
"0.0.1-alpha.10|macos_arm64|sha256:0000000000000000000000000000000000000000000000000000000000000000|5000000",
|
|
31
|
+
"0.0.1-alpha.10|macos_x86_64|sha256:0000000000000000000000000000000000000000000000000000000000000000|5000000",
|
|
32
|
+
"0.0.1-alpha.10|linux_arm64|sha256:0000000000000000000000000000000000000000000000000000000000000000|5000000",
|
|
33
|
+
"0.0.1-alpha.10|linux_x86_64|sha256:0000000000000000000000000000000000000000000000000000000000000000|5000000",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
def generate_url(self, plat: Platform) -> str:
|
|
37
|
+
"""Generate download URL for ty."""
|
|
38
|
+
version = self.version
|
|
39
|
+
platform_mapping = {
|
|
40
|
+
"macos_arm64": "aarch64-apple-darwin",
|
|
41
|
+
"macos_x86_64": "x86_64-apple-darwin",
|
|
42
|
+
"linux_arm64": "aarch64-unknown-linux-gnu",
|
|
43
|
+
"linux_x86_64": "x86_64-unknown-linux-gnu",
|
|
44
|
+
}
|
|
45
|
+
plat_str = platform_mapping.get(plat.value, "x86_64-unknown-linux-gnu")
|
|
46
|
+
return f"https://github.com/astral-sh/ty/releases/download/{version}/ty-{plat_str}.tar.gz"
|
|
47
|
+
|
|
48
|
+
def generate_exe(self, plat: Platform) -> str:
|
|
49
|
+
"""Return the path to the ty executable within the downloaded archive."""
|
|
50
|
+
return "ty"
|
|
30
51
|
|
|
31
52
|
# Type checking mode
|
|
32
53
|
strict = BoolOption(
|
pants_baseline/subsystems/uv.py
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from pants.core.util_rules.external_tool import ExternalTool
|
|
6
|
+
from pants.engine.platform import Platform
|
|
5
7
|
from pants.option.option_types import BoolOption, StrListOption, StrOption
|
|
6
|
-
from pants.option.subsystem import Subsystem
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
class UvSubsystem(
|
|
10
|
+
class UvSubsystem(ExternalTool):
|
|
10
11
|
"""Configuration for uv dependency management and security auditing.
|
|
11
12
|
|
|
12
13
|
uv is Astral's ultra-fast Python package installer and resolver,
|
|
@@ -21,10 +22,30 @@ class UvSubsystem(Subsystem):
|
|
|
21
22
|
options_scope = "baseline-uv"
|
|
22
23
|
help = "uv dependency management and security auditing configuration for baseline plugin."
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
default_version = "0.5.21"
|
|
26
|
+
default_known_versions = [
|
|
27
|
+
# uv 0.5.21
|
|
28
|
+
"0.5.21|macos_arm64|sha256:0000000000000000000000000000000000000000000000000000000000000000|15000000",
|
|
29
|
+
"0.5.21|macos_x86_64|sha256:0000000000000000000000000000000000000000000000000000000000000000|15000000",
|
|
30
|
+
"0.5.21|linux_arm64|sha256:0000000000000000000000000000000000000000000000000000000000000000|15000000",
|
|
31
|
+
"0.5.21|linux_x86_64|sha256:0000000000000000000000000000000000000000000000000000000000000000|15000000",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
def generate_url(self, plat: Platform) -> str:
|
|
35
|
+
"""Generate download URL for uv."""
|
|
36
|
+
version = self.version
|
|
37
|
+
platform_mapping = {
|
|
38
|
+
"macos_arm64": "aarch64-apple-darwin",
|
|
39
|
+
"macos_x86_64": "x86_64-apple-darwin",
|
|
40
|
+
"linux_arm64": "aarch64-unknown-linux-gnu",
|
|
41
|
+
"linux_x86_64": "x86_64-unknown-linux-gnu",
|
|
42
|
+
}
|
|
43
|
+
plat_str = platform_mapping.get(plat.value, "x86_64-unknown-linux-gnu")
|
|
44
|
+
return f"https://github.com/astral-sh/uv/releases/download/{version}/uv-{plat_str}.tar.gz"
|
|
45
|
+
|
|
46
|
+
def generate_exe(self, plat: Platform) -> str:
|
|
47
|
+
"""Return the path to the uv executable within the downloaded archive."""
|
|
48
|
+
return "uv"
|
|
28
49
|
|
|
29
50
|
# Security auditing
|
|
30
51
|
audit_enabled = BoolOption(
|
pants_baseline/targets.py
CHANGED
|
@@ -6,25 +6,26 @@ from pants.engine.target import (
|
|
|
6
6
|
COMMON_TARGET_FIELDS,
|
|
7
7
|
BoolField,
|
|
8
8
|
IntField,
|
|
9
|
+
MultipleSourcesField,
|
|
9
10
|
StringField,
|
|
10
|
-
StringSequenceField,
|
|
11
11
|
Target,
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class BaselineSourcesField(
|
|
15
|
+
class BaselineSourcesField(MultipleSourcesField):
|
|
16
16
|
"""Source files for the baseline Python project."""
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
default = ("src/**/*.py",)
|
|
19
|
+
expected_file_extensions = (".py", ".pyi")
|
|
20
20
|
help = "Python source files to include in baseline checks."
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class BaselineTestSourcesField(
|
|
23
|
+
class BaselineTestSourcesField(MultipleSourcesField):
|
|
24
24
|
"""Test source files for the baseline Python project."""
|
|
25
25
|
|
|
26
26
|
alias = "test_sources"
|
|
27
27
|
default = ("tests/**/*.py",)
|
|
28
|
+
expected_file_extensions = (".py", ".pyi")
|
|
28
29
|
help = "Test files to include in baseline checks."
|
|
29
30
|
|
|
30
31
|
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
pants_baseline/__about__.py,sha256=T4K8CIb9JqzctGI3L4wC9eqzNvM2MGkrz714dtsWrmA,98
|
|
2
|
-
pants_baseline/__init__.py,sha256=uVRGi1D2gFjc7emmeewWdcvpO-NsUuKsMbX3rztOxWU,655
|
|
3
|
-
pants_baseline/register.py,sha256=MGOvpu2gCbv9sa-aYnsb-fsGilKi2I1yVpNARWFggCM,1528
|
|
4
|
-
pants_baseline/targets.py,sha256=G8ejj3QYaGHtLHbxirTyTjnEAWYxlpHFHYKV-_B4lMo,3300
|
|
5
|
-
pants_baseline/goals/__init__.py,sha256=pf6KU2CIQuDkx8ER3IS0H-kuNbBtX-AH5B5SnSP9_yw,192
|
|
6
|
-
pants_baseline/goals/audit.py,sha256=i7zyyKssWw6EE2zN5putWP9sikkcjUKn7g3Jrapv994,2380
|
|
7
|
-
pants_baseline/goals/fmt.py,sha256=etZHJRrST904L7ljU0r2xRlUbFA42gvhxmvLhxdZ5oA,1794
|
|
8
|
-
pants_baseline/goals/lint.py,sha256=_o_7Bt-w6mHslN7xwvu51NrM_mlh6TJLxe7JizA7Tfk,1930
|
|
9
|
-
pants_baseline/goals/test.py,sha256=THW4kJAFbAzPCjLbq1dxg81T19QdywXYiwTNKSB4z8M,1653
|
|
10
|
-
pants_baseline/goals/typecheck.py,sha256=AOFhJchdGgc6mm_4u5kGTqr2gTVVH6j7ZPRQ7oI1R0c,1769
|
|
11
|
-
pants_baseline/rules/__init__.py,sha256=UpvDpGVImhRfp2_VeUNsRPGiWjBbMI6AV1-Yx3kS0Gg,252
|
|
12
|
-
pants_baseline/rules/audit_rules.py,sha256=0HbFdo89CwiVBKvkABDpFJ8bOKnQhV1-guT_pFdwAnQ,1889
|
|
13
|
-
pants_baseline/rules/fmt_rules.py,sha256=BXw6ckUPFaBM2WFWWA8JjDa6CFdenNulNAUWjwsfJV0,3563
|
|
14
|
-
pants_baseline/rules/lint_rules.py,sha256=JCrjGMgv3buUyN5mK9_vlo-StjJjnKkOIv_5Zipy2Bs,3851
|
|
15
|
-
pants_baseline/rules/test_rules.py,sha256=jj4lk3-mueOPujPFPK2TCdBFZZA_vovdDdHED9jGp7U,4225
|
|
16
|
-
pants_baseline/rules/typecheck_rules.py,sha256=oDc-WcNdrv0zYHE6wj65la8YAjJkoDMWCox3SW1pIxc,3995
|
|
17
|
-
pants_baseline/subsystems/__init__.py,sha256=LteH_qmUIgRAnXYmmi7f6o894QfpY3hMNH5dlvJbSoM,387
|
|
18
|
-
pants_baseline/subsystems/baseline.py,sha256=M20muLytoWZnA4ZY3lkbSsdCXt6OMPH6IMJfXULAQSo,2049
|
|
19
|
-
pants_baseline/subsystems/ruff.py,sha256=v0yHmbdgsPMMgjxJrs-YaKPE_n7rE6h-D0HGhXheyyE,2601
|
|
20
|
-
pants_baseline/subsystems/ty.py,sha256=6M205VZD5TpX6T4vWZ4UFs5Y3T2rGqYtzidmiRh_6kg,2126
|
|
21
|
-
pants_baseline/subsystems/uv.py,sha256=K6G8KR3l-Jo18aMh183gfhEelJR57cb20yIqKUMw3K0,1851
|
|
22
|
-
jaymd96_pants_baseline-0.1.7.dist-info/METADATA,sha256=0wuOSC3UtXOlLTwioj7jphpF3y0awgduawPCo0vF_-c,7934
|
|
23
|
-
jaymd96_pants_baseline-0.1.7.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
24
|
-
jaymd96_pants_baseline-0.1.7.dist-info/licenses/LICENSE,sha256=oLGLZv7XKM_oKCbdMW1bZB37SXsdexmhNSuh3Xg4m4I,10754
|
|
25
|
-
jaymd96_pants_baseline-0.1.7.dist-info/RECORD,,
|
|
File without changes
|
{jaymd96_pants_baseline-0.1.7.dist-info → jaymd96_pants_baseline-0.2.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|