pants-ty 0.1.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.
- pants_ty-0.1.0/LICENSE +21 -0
- pants_ty-0.1.0/PKG-INFO +163 -0
- pants_ty-0.1.0/README.md +144 -0
- pants_ty-0.1.0/pants-plugins/pants_ty/__init__.py +2 -0
- pants_ty-0.1.0/pants-plugins/pants_ty/register.py +13 -0
- pants_ty-0.1.0/pants-plugins/pants_ty/rules.py +291 -0
- pants_ty-0.1.0/pants-plugins/pants_ty/skip_field.py +30 -0
- pants_ty-0.1.0/pants-plugins/pants_ty/subsystem.py +99 -0
- pants_ty-0.1.0/pants-plugins/pants_ty.egg-info/PKG-INFO +163 -0
- pants_ty-0.1.0/pants-plugins/pants_ty.egg-info/SOURCES.txt +13 -0
- pants_ty-0.1.0/pants-plugins/pants_ty.egg-info/dependency_links.txt +1 -0
- pants_ty-0.1.0/pants-plugins/pants_ty.egg-info/requires.txt +1 -0
- pants_ty-0.1.0/pants-plugins/pants_ty.egg-info/top_level.txt +1 -0
- pants_ty-0.1.0/pyproject.toml +37 -0
- pants_ty-0.1.0/setup.cfg +4 -0
pants_ty-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vasile Razdalovschi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pants_ty-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pants-ty
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Pants check backend for the Astral ty Python type checker.
|
|
5
|
+
Author: Vasile Razdalovschi
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/vrazdalovschi/pants-ty-plugin
|
|
8
|
+
Project-URL: Issues, https://github.com/vrazdalovschi/pants-ty-plugin/issues
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: pantsbuild.pants<2.32,>=2.31
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# pants-ty-plugin
|
|
21
|
+
|
|
22
|
+
`pants-ty-plugin` adds a Pants `check` backend for [Astral ty](https://docs.astral.sh/ty/).
|
|
23
|
+
|
|
24
|
+
It is designed for Pants `2.31.x` and currently supports Linux and macOS. The backend installs
|
|
25
|
+
`ty` as an external binary, then runs it with:
|
|
26
|
+
|
|
27
|
+
- a resolve-backed Python environment for third-party dependencies
|
|
28
|
+
- Pants source roots as `--extra-search-path` entries for first-party imports
|
|
29
|
+
|
|
30
|
+
That means `ty` can resolve imports that Pants already knows about.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- `pants check --only=ty ...`
|
|
35
|
+
- `skip_ty = true` on Python targets
|
|
36
|
+
- `ty.toml` discovery
|
|
37
|
+
- `[tool.ty]` discovery from `pyproject.toml`
|
|
38
|
+
- resolve-aware `--python`
|
|
39
|
+
- source-root-aware `--extra-search-path`
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
### Option 1: vendor the plugin into a private repo
|
|
44
|
+
|
|
45
|
+
Copy only the Python package files from `pants-plugins/pants_ty/` into your repo's
|
|
46
|
+
`pants-plugins/pants_ty/` directory:
|
|
47
|
+
|
|
48
|
+
- `__init__.py`
|
|
49
|
+
- `register.py`
|
|
50
|
+
- `rules.py`
|
|
51
|
+
- `skip_field.py`
|
|
52
|
+
- `subsystem.py`
|
|
53
|
+
|
|
54
|
+
Do not copy this plugin repo's development-only files:
|
|
55
|
+
|
|
56
|
+
- `pants-plugins/BUILD`
|
|
57
|
+
- `pants-plugins/pants_ty/BUILD`
|
|
58
|
+
- `pants-plugins/lock.txt`
|
|
59
|
+
- `tests/`
|
|
60
|
+
- this repo's `pants.toml`, `pyproject.toml`, or GitHub workflow files
|
|
61
|
+
|
|
62
|
+
Those files are only for developing and releasing `pants-ty-plugin` itself. A consuming repo
|
|
63
|
+
should use its own resolves, lockfiles, and test setup.
|
|
64
|
+
|
|
65
|
+
Then configure:
|
|
66
|
+
|
|
67
|
+
```toml
|
|
68
|
+
[GLOBAL]
|
|
69
|
+
pants_version = "2.31.0"
|
|
70
|
+
backend_packages = [
|
|
71
|
+
"pants.backend.python",
|
|
72
|
+
"pants_ty",
|
|
73
|
+
]
|
|
74
|
+
pythonpath = ["%(buildroot)s/pants-plugins"]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If you accidentally copy the dev `BUILD` files too, you may see an error like:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
UnrecognizedResolveNamesError: ... resolve ... pants-plugins
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
That means your consuming repo picked up this repo's internal development resolve. Remove the
|
|
84
|
+
copied `BUILD` files and keep only the plugin Python modules.
|
|
85
|
+
|
|
86
|
+
### Option 2: install as a published plugin
|
|
87
|
+
|
|
88
|
+
Once the package is published, use:
|
|
89
|
+
|
|
90
|
+
```toml
|
|
91
|
+
[GLOBAL]
|
|
92
|
+
plugins = ["pants-ty==0.1.0"]
|
|
93
|
+
backend_packages = [
|
|
94
|
+
"pants.backend.python",
|
|
95
|
+
"pants_ty",
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Configure
|
|
100
|
+
|
|
101
|
+
Create either `ty.toml` or add `[tool.ty]` to `pyproject.toml`.
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
|
|
105
|
+
```toml
|
|
106
|
+
[tool.ty]
|
|
107
|
+
exclude = [".pants.d", "dist"]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Pants exposes the plugin options under `[ty]`:
|
|
111
|
+
|
|
112
|
+
```toml
|
|
113
|
+
[ty]
|
|
114
|
+
args = ["--output-format=concise"]
|
|
115
|
+
config_discovery = true
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Useful commands:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pants help ty
|
|
122
|
+
pants check --only=ty ::
|
|
123
|
+
pants check --only=ty path/to/pkg::
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
To skip a target:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
python_sources(
|
|
130
|
+
name="lib",
|
|
131
|
+
skip_ty=True,
|
|
132
|
+
)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Development
|
|
136
|
+
|
|
137
|
+
This repo uses Pants to lint, test, and dogfood the plugin itself.
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
ruff check pants-plugins tests
|
|
141
|
+
pants test ::
|
|
142
|
+
pants check ::
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
To build a distributable wheel and sdist:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
python -m build
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Repository layout
|
|
152
|
+
|
|
153
|
+
- `pants-plugins/pants_ty`: plugin source
|
|
154
|
+
- `tests/pants_ty`: unit and integration tests
|
|
155
|
+
- `pants.toml`: local development config
|
|
156
|
+
- `pants.ci.toml`: CI-specific Pants settings
|
|
157
|
+
|
|
158
|
+
## Notes
|
|
159
|
+
|
|
160
|
+
- The Pants plugin API is not stable across minor versions. This repo currently targets
|
|
161
|
+
Pants `2.31.x`.
|
|
162
|
+
- The backend only resolves imports that Pants already knows through source roots and
|
|
163
|
+
target resolves.
|
pants_ty-0.1.0/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# pants-ty-plugin
|
|
2
|
+
|
|
3
|
+
`pants-ty-plugin` adds a Pants `check` backend for [Astral ty](https://docs.astral.sh/ty/).
|
|
4
|
+
|
|
5
|
+
It is designed for Pants `2.31.x` and currently supports Linux and macOS. The backend installs
|
|
6
|
+
`ty` as an external binary, then runs it with:
|
|
7
|
+
|
|
8
|
+
- a resolve-backed Python environment for third-party dependencies
|
|
9
|
+
- Pants source roots as `--extra-search-path` entries for first-party imports
|
|
10
|
+
|
|
11
|
+
That means `ty` can resolve imports that Pants already knows about.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- `pants check --only=ty ...`
|
|
16
|
+
- `skip_ty = true` on Python targets
|
|
17
|
+
- `ty.toml` discovery
|
|
18
|
+
- `[tool.ty]` discovery from `pyproject.toml`
|
|
19
|
+
- resolve-aware `--python`
|
|
20
|
+
- source-root-aware `--extra-search-path`
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
### Option 1: vendor the plugin into a private repo
|
|
25
|
+
|
|
26
|
+
Copy only the Python package files from `pants-plugins/pants_ty/` into your repo's
|
|
27
|
+
`pants-plugins/pants_ty/` directory:
|
|
28
|
+
|
|
29
|
+
- `__init__.py`
|
|
30
|
+
- `register.py`
|
|
31
|
+
- `rules.py`
|
|
32
|
+
- `skip_field.py`
|
|
33
|
+
- `subsystem.py`
|
|
34
|
+
|
|
35
|
+
Do not copy this plugin repo's development-only files:
|
|
36
|
+
|
|
37
|
+
- `pants-plugins/BUILD`
|
|
38
|
+
- `pants-plugins/pants_ty/BUILD`
|
|
39
|
+
- `pants-plugins/lock.txt`
|
|
40
|
+
- `tests/`
|
|
41
|
+
- this repo's `pants.toml`, `pyproject.toml`, or GitHub workflow files
|
|
42
|
+
|
|
43
|
+
Those files are only for developing and releasing `pants-ty-plugin` itself. A consuming repo
|
|
44
|
+
should use its own resolves, lockfiles, and test setup.
|
|
45
|
+
|
|
46
|
+
Then configure:
|
|
47
|
+
|
|
48
|
+
```toml
|
|
49
|
+
[GLOBAL]
|
|
50
|
+
pants_version = "2.31.0"
|
|
51
|
+
backend_packages = [
|
|
52
|
+
"pants.backend.python",
|
|
53
|
+
"pants_ty",
|
|
54
|
+
]
|
|
55
|
+
pythonpath = ["%(buildroot)s/pants-plugins"]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If you accidentally copy the dev `BUILD` files too, you may see an error like:
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
UnrecognizedResolveNamesError: ... resolve ... pants-plugins
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
That means your consuming repo picked up this repo's internal development resolve. Remove the
|
|
65
|
+
copied `BUILD` files and keep only the plugin Python modules.
|
|
66
|
+
|
|
67
|
+
### Option 2: install as a published plugin
|
|
68
|
+
|
|
69
|
+
Once the package is published, use:
|
|
70
|
+
|
|
71
|
+
```toml
|
|
72
|
+
[GLOBAL]
|
|
73
|
+
plugins = ["pants-ty==0.1.0"]
|
|
74
|
+
backend_packages = [
|
|
75
|
+
"pants.backend.python",
|
|
76
|
+
"pants_ty",
|
|
77
|
+
]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Configure
|
|
81
|
+
|
|
82
|
+
Create either `ty.toml` or add `[tool.ty]` to `pyproject.toml`.
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
|
|
86
|
+
```toml
|
|
87
|
+
[tool.ty]
|
|
88
|
+
exclude = [".pants.d", "dist"]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Pants exposes the plugin options under `[ty]`:
|
|
92
|
+
|
|
93
|
+
```toml
|
|
94
|
+
[ty]
|
|
95
|
+
args = ["--output-format=concise"]
|
|
96
|
+
config_discovery = true
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Useful commands:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
pants help ty
|
|
103
|
+
pants check --only=ty ::
|
|
104
|
+
pants check --only=ty path/to/pkg::
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
To skip a target:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
python_sources(
|
|
111
|
+
name="lib",
|
|
112
|
+
skip_ty=True,
|
|
113
|
+
)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Development
|
|
117
|
+
|
|
118
|
+
This repo uses Pants to lint, test, and dogfood the plugin itself.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
ruff check pants-plugins tests
|
|
122
|
+
pants test ::
|
|
123
|
+
pants check ::
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
To build a distributable wheel and sdist:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
python -m build
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Repository layout
|
|
133
|
+
|
|
134
|
+
- `pants-plugins/pants_ty`: plugin source
|
|
135
|
+
- `tests/pants_ty`: unit and integration tests
|
|
136
|
+
- `pants.toml`: local development config
|
|
137
|
+
- `pants.ci.toml`: CI-specific Pants settings
|
|
138
|
+
|
|
139
|
+
## Notes
|
|
140
|
+
|
|
141
|
+
- The Pants plugin API is not stable across minor versions. This repo currently targets
|
|
142
|
+
Pants `2.31.x`.
|
|
143
|
+
- The backend only resolves imports that Pants already knows through source roots and
|
|
144
|
+
target resolves.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
|
|
5
|
+
from pants.engine.rules import Rule
|
|
6
|
+
from pants.engine.unions import UnionRule
|
|
7
|
+
|
|
8
|
+
from pants_ty import rules as ty_rules
|
|
9
|
+
from pants_ty import skip_field, subsystem
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def rules() -> Iterable[Rule | UnionRule]:
|
|
13
|
+
return (*subsystem.rules(), *skip_field.rules(), *ty_rules.rules())
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from collections.abc import Iterable, Sequence
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from pants.backend.python.subsystems.setup import PythonSetup
|
|
8
|
+
from pants.backend.python.target_types import (
|
|
9
|
+
InterpreterConstraintsField,
|
|
10
|
+
PythonResolveField,
|
|
11
|
+
PythonSourceField,
|
|
12
|
+
)
|
|
13
|
+
from pants.backend.python.util_rules import pex_from_targets
|
|
14
|
+
from pants.backend.python.util_rules.interpreter_constraints import InterpreterConstraints
|
|
15
|
+
from pants.backend.python.util_rules.partition import (
|
|
16
|
+
_partition_by_interpreter_constraints_and_resolve,
|
|
17
|
+
)
|
|
18
|
+
from pants.backend.python.util_rules.pex import (
|
|
19
|
+
PexRequest,
|
|
20
|
+
VenvPexProcess,
|
|
21
|
+
VenvPexRequest,
|
|
22
|
+
create_pex,
|
|
23
|
+
create_venv_pex,
|
|
24
|
+
)
|
|
25
|
+
from pants.backend.python.util_rules.pex_environment import PexEnvironment
|
|
26
|
+
from pants.backend.python.util_rules.pex_from_targets import RequirementsPexRequest
|
|
27
|
+
from pants.backend.python.util_rules.python_sources import (
|
|
28
|
+
PythonSourceFilesRequest,
|
|
29
|
+
prepare_python_sources,
|
|
30
|
+
)
|
|
31
|
+
from pants.core.goals.check import CheckRequest, CheckResult, CheckResults
|
|
32
|
+
from pants.core.util_rules import config_files
|
|
33
|
+
from pants.core.util_rules.config_files import find_config_file
|
|
34
|
+
from pants.core.util_rules.external_tool import download_external_tool
|
|
35
|
+
from pants.core.util_rules.source_files import SourceFilesRequest, determine_source_files
|
|
36
|
+
from pants.engine.collection import Collection
|
|
37
|
+
from pants.engine.fs import MergeDigests
|
|
38
|
+
from pants.engine.internals.graph import resolve_coarsened_targets
|
|
39
|
+
from pants.engine.intrinsics import execute_process, merge_digests
|
|
40
|
+
from pants.engine.platform import Platform
|
|
41
|
+
from pants.engine.process import Process, ProcessCacheScope, execute_process_or_raise
|
|
42
|
+
from pants.engine.rules import Rule, collect_rules, concurrently, implicitly, rule
|
|
43
|
+
from pants.engine.target import (
|
|
44
|
+
CoarsenedTargets,
|
|
45
|
+
CoarsenedTargetsRequest,
|
|
46
|
+
FieldSet,
|
|
47
|
+
Target,
|
|
48
|
+
)
|
|
49
|
+
from pants.engine.unions import UnionRule
|
|
50
|
+
from pants.util.logging import LogLevel
|
|
51
|
+
from pants.util.ordered_set import FrozenOrderedSet, OrderedSet
|
|
52
|
+
from pants.util.strutil import pluralize
|
|
53
|
+
|
|
54
|
+
from pants_ty.skip_field import SkipTyField
|
|
55
|
+
from pants_ty.subsystem import Ty
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _python_version_args(
|
|
59
|
+
*, python_version: str | None, user_args: Sequence[str]
|
|
60
|
+
) -> tuple[str, ...]:
|
|
61
|
+
if python_version is None:
|
|
62
|
+
return ()
|
|
63
|
+
if any(
|
|
64
|
+
arg.startswith("--python-version=") or arg.startswith("--target-version=")
|
|
65
|
+
for arg in user_args
|
|
66
|
+
):
|
|
67
|
+
return ()
|
|
68
|
+
return (f"--python-version={python_version}",)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _extra_search_path_args(source_roots: Sequence[str]) -> tuple[str, ...]:
|
|
72
|
+
unique_source_roots = tuple(dict.fromkeys(source_roots))
|
|
73
|
+
return tuple(f"--extra-search-path={source_root}" for source_root in unique_source_roots)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _batch_input_paths(
|
|
77
|
+
paths: Sequence[str], *, max_paths_per_batch: int
|
|
78
|
+
) -> tuple[tuple[str, ...], ...]:
|
|
79
|
+
if max_paths_per_batch <= 0:
|
|
80
|
+
raise ValueError("max_paths_per_batch must be positive")
|
|
81
|
+
if not paths:
|
|
82
|
+
return ()
|
|
83
|
+
return tuple(
|
|
84
|
+
tuple(paths[index : index + max_paths_per_batch])
|
|
85
|
+
for index in range(0, len(paths), max_paths_per_batch)
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass(frozen=True)
|
|
90
|
+
class TyFieldSet(FieldSet):
|
|
91
|
+
required_fields = (PythonSourceField,)
|
|
92
|
+
|
|
93
|
+
sources: PythonSourceField
|
|
94
|
+
resolve: PythonResolveField
|
|
95
|
+
interpreter_constraints: InterpreterConstraintsField
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def opt_out(cls, tgt: Target) -> bool:
|
|
99
|
+
return tgt.get(SkipTyField).value
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class TyRequest(CheckRequest):
|
|
103
|
+
field_set_type = TyFieldSet
|
|
104
|
+
tool_name = Ty.options_scope
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@dataclass(frozen=True)
|
|
108
|
+
class TyPartition:
|
|
109
|
+
field_sets: FrozenOrderedSet[TyFieldSet]
|
|
110
|
+
root_targets: CoarsenedTargets
|
|
111
|
+
resolve_description: str | None
|
|
112
|
+
interpreter_constraints: InterpreterConstraints
|
|
113
|
+
|
|
114
|
+
def description(self) -> str:
|
|
115
|
+
ics = str(sorted(str(c) for c in self.interpreter_constraints))
|
|
116
|
+
return f"{self.resolve_description}, {ics}" if self.resolve_description else ics
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class TyPartitions(Collection[TyPartition]):
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@rule(
|
|
124
|
+
desc="Determine if it is necessary to partition Ty's input",
|
|
125
|
+
level=LogLevel.DEBUG,
|
|
126
|
+
)
|
|
127
|
+
async def ty_determine_partitions(
|
|
128
|
+
request: TyRequest,
|
|
129
|
+
ty: Ty,
|
|
130
|
+
python_setup: PythonSetup,
|
|
131
|
+
) -> TyPartitions:
|
|
132
|
+
resolve_and_interpreter_constraints_to_field_sets = (
|
|
133
|
+
_partition_by_interpreter_constraints_and_resolve(request.field_sets, python_setup)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
coarsened_targets = await resolve_coarsened_targets(
|
|
137
|
+
CoarsenedTargetsRequest(field_set.address for field_set in request.field_sets),
|
|
138
|
+
**implicitly(),
|
|
139
|
+
)
|
|
140
|
+
coarsened_targets_by_address = coarsened_targets.by_address()
|
|
141
|
+
|
|
142
|
+
return TyPartitions(
|
|
143
|
+
TyPartition(
|
|
144
|
+
FrozenOrderedSet(field_sets),
|
|
145
|
+
CoarsenedTargets(
|
|
146
|
+
OrderedSet(
|
|
147
|
+
coarsened_targets_by_address[field_set.address] for field_set in field_sets
|
|
148
|
+
)
|
|
149
|
+
),
|
|
150
|
+
resolve if len(python_setup.resolves) > 1 else None,
|
|
151
|
+
interpreter_constraints or ty.interpreter_constraints,
|
|
152
|
+
)
|
|
153
|
+
for (resolve, interpreter_constraints), field_sets in sorted(
|
|
154
|
+
resolve_and_interpreter_constraints_to_field_sets.items()
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@rule(desc="Typecheck one Ty partition", level=LogLevel.DEBUG)
|
|
160
|
+
async def ty_typecheck_partition(
|
|
161
|
+
partition: TyPartition,
|
|
162
|
+
ty: Ty,
|
|
163
|
+
platform: Platform,
|
|
164
|
+
pex_environment: PexEnvironment,
|
|
165
|
+
python_setup: PythonSetup,
|
|
166
|
+
) -> CheckResult:
|
|
167
|
+
(
|
|
168
|
+
ty_tool,
|
|
169
|
+
config_files_snapshot,
|
|
170
|
+
root_sources,
|
|
171
|
+
transitive_sources,
|
|
172
|
+
requirements_pex,
|
|
173
|
+
) = await concurrently(
|
|
174
|
+
download_external_tool(ty.get_request(platform)),
|
|
175
|
+
find_config_file(ty.config_request()),
|
|
176
|
+
determine_source_files(SourceFilesRequest(fs.sources for fs in partition.field_sets)),
|
|
177
|
+
prepare_python_sources(
|
|
178
|
+
PythonSourceFilesRequest(partition.root_targets.closure()), **implicitly()
|
|
179
|
+
),
|
|
180
|
+
create_pex(
|
|
181
|
+
**implicitly(
|
|
182
|
+
RequirementsPexRequest(
|
|
183
|
+
(fs.address for fs in partition.field_sets),
|
|
184
|
+
hardcoded_interpreter_constraints=partition.interpreter_constraints,
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
complete_pex_env = pex_environment.in_workspace()
|
|
191
|
+
requirements_venv_pex = await create_venv_pex(
|
|
192
|
+
VenvPexRequest(
|
|
193
|
+
PexRequest(
|
|
194
|
+
output_filename="requirements_venv.pex",
|
|
195
|
+
internal_only=True,
|
|
196
|
+
pex_path=[requirements_pex],
|
|
197
|
+
interpreter_constraints=partition.interpreter_constraints,
|
|
198
|
+
),
|
|
199
|
+
complete_pex_env,
|
|
200
|
+
),
|
|
201
|
+
**implicitly(),
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
_ = await execute_process_or_raise(
|
|
205
|
+
**implicitly(
|
|
206
|
+
VenvPexProcess(
|
|
207
|
+
requirements_venv_pex,
|
|
208
|
+
description="Force Ty requirements venv to materialize",
|
|
209
|
+
argv=["-c", "''"],
|
|
210
|
+
cache_scope=ProcessCacheScope.PER_SESSION,
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
input_digest = await merge_digests(
|
|
216
|
+
MergeDigests(
|
|
217
|
+
(
|
|
218
|
+
transitive_sources.source_files.snapshot.digest,
|
|
219
|
+
config_files_snapshot.snapshot.digest,
|
|
220
|
+
requirements_venv_pex.digest,
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
immutable_input_key = "__ty_tool"
|
|
226
|
+
exe_path = os.path.join(immutable_input_key, ty_tool.exe)
|
|
227
|
+
requirements_venv_path = os.path.join(
|
|
228
|
+
complete_pex_env.pex_root, requirements_venv_pex.venv_rel_dir
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
python_version = partition.interpreter_constraints.minimum_python_version(
|
|
232
|
+
python_setup.interpreter_versions_universe
|
|
233
|
+
)
|
|
234
|
+
config_args = (f"--config-file={ty.config}",) if ty.config else ()
|
|
235
|
+
common_args = (
|
|
236
|
+
"check",
|
|
237
|
+
*config_args,
|
|
238
|
+
f"--python={requirements_venv_path}",
|
|
239
|
+
*_python_version_args(python_version=python_version, user_args=ty.args),
|
|
240
|
+
*_extra_search_path_args(transitive_sources.source_roots),
|
|
241
|
+
*ty.args,
|
|
242
|
+
)
|
|
243
|
+
path_batches = _batch_input_paths(tuple(root_sources.snapshot.files), max_paths_per_batch=512)
|
|
244
|
+
|
|
245
|
+
if not path_batches:
|
|
246
|
+
return CheckResult(0, "", "", partition_description=partition.description())
|
|
247
|
+
|
|
248
|
+
batch_results = await concurrently(
|
|
249
|
+
execute_process(
|
|
250
|
+
Process(
|
|
251
|
+
argv=(exe_path, *common_args, *path_batch),
|
|
252
|
+
input_digest=input_digest,
|
|
253
|
+
immutable_input_digests={immutable_input_key: ty_tool.digest},
|
|
254
|
+
description=f"Run Ty on {pluralize(len(path_batch), 'file')}.",
|
|
255
|
+
level=LogLevel.DEBUG,
|
|
256
|
+
),
|
|
257
|
+
**implicitly(),
|
|
258
|
+
)
|
|
259
|
+
for path_batch in path_batches
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
return CheckResult(
|
|
263
|
+
exit_code=max(result.exit_code for result in batch_results),
|
|
264
|
+
stdout="".join(result.stdout.decode() for result in batch_results),
|
|
265
|
+
stderr="".join(result.stderr.decode() for result in batch_results),
|
|
266
|
+
partition_description=partition.description(),
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@rule(desc="Typecheck using Ty", level=LogLevel.DEBUG)
|
|
271
|
+
async def ty_typecheck(
|
|
272
|
+
request: TyRequest,
|
|
273
|
+
ty: Ty,
|
|
274
|
+
) -> CheckResults:
|
|
275
|
+
if ty.skip:
|
|
276
|
+
return CheckResults([], checker_name=request.tool_name)
|
|
277
|
+
|
|
278
|
+
partitions = await ty_determine_partitions(request, **implicitly())
|
|
279
|
+
partitioned_results = await concurrently(
|
|
280
|
+
ty_typecheck_partition(partition, **implicitly()) for partition in partitions
|
|
281
|
+
)
|
|
282
|
+
return CheckResults(partitioned_results, checker_name=request.tool_name)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def rules() -> Iterable[Rule | UnionRule]:
|
|
286
|
+
return (
|
|
287
|
+
*collect_rules(),
|
|
288
|
+
*config_files.rules(),
|
|
289
|
+
*pex_from_targets.rules(),
|
|
290
|
+
UnionRule(CheckRequest, TyRequest),
|
|
291
|
+
)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
|
|
5
|
+
from pants.backend.python.target_types import (
|
|
6
|
+
PythonSourceTarget,
|
|
7
|
+
PythonSourcesGeneratorTarget,
|
|
8
|
+
PythonTestTarget,
|
|
9
|
+
PythonTestsGeneratorTarget,
|
|
10
|
+
PythonTestUtilsGeneratorTarget,
|
|
11
|
+
)
|
|
12
|
+
from pants.engine.rules import Rule
|
|
13
|
+
from pants.engine.target import BoolField
|
|
14
|
+
from pants.engine.unions import UnionRule
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SkipTyField(BoolField):
|
|
18
|
+
alias = "skip_ty"
|
|
19
|
+
default = False
|
|
20
|
+
help = "If true, don't run Ty on this target's code."
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def rules() -> Iterable[Rule | UnionRule]:
|
|
24
|
+
return (
|
|
25
|
+
PythonSourcesGeneratorTarget.register_plugin_field(SkipTyField),
|
|
26
|
+
PythonSourceTarget.register_plugin_field(SkipTyField),
|
|
27
|
+
PythonTestsGeneratorTarget.register_plugin_field(SkipTyField),
|
|
28
|
+
PythonTestTarget.register_plugin_field(SkipTyField),
|
|
29
|
+
PythonTestUtilsGeneratorTarget.register_plugin_field(SkipTyField),
|
|
30
|
+
)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
|
|
5
|
+
from pants.backend.python.util_rules.interpreter_constraints import InterpreterConstraints
|
|
6
|
+
from pants.core.goals.resolves import ExportableTool
|
|
7
|
+
from pants.core.util_rules.config_files import ConfigFilesRequest
|
|
8
|
+
from pants.core.util_rules.external_tool import TemplatedExternalTool
|
|
9
|
+
from pants.engine.platform import Platform
|
|
10
|
+
from pants.engine.rules import Rule, collect_rules
|
|
11
|
+
from pants.engine.unions import UnionRule
|
|
12
|
+
from pants.option.option_types import (
|
|
13
|
+
ArgsListOption,
|
|
14
|
+
BoolOption,
|
|
15
|
+
FileOption,
|
|
16
|
+
SkipOption,
|
|
17
|
+
StrListOption,
|
|
18
|
+
)
|
|
19
|
+
from pants.util.strutil import softwrap
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Ty(TemplatedExternalTool):
|
|
23
|
+
options_scope = "ty"
|
|
24
|
+
name = "Ty"
|
|
25
|
+
help = softwrap(
|
|
26
|
+
"""
|
|
27
|
+
The Ty Python type checker (https://docs.astral.sh/ty/).
|
|
28
|
+
"""
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
default_version = "0.0.24"
|
|
32
|
+
default_known_versions = [
|
|
33
|
+
"0.0.24|linux_arm64|f51f5c0fcdf06f22cf74edbc15fddb2614466a3237ec12247e6aaf6215d349ee|9778744",
|
|
34
|
+
"0.0.24|linux_x86_64|dbb8d08643dc2ce7dee5a1c482e1ab240d4e6eb5ae7df08b77f59df8c6374014|10612104",
|
|
35
|
+
"0.0.24|macos_arm64|91709778a139350dc890e6048b042bc0800b04f1cb0cd4a636af22673fa84c1a|9323636",
|
|
36
|
+
"0.0.24|macos_x86_64|3c0f93d0b578b556f4a7765714f6e875f836f8f0d0111fdc786b2adc79110a4d|9957953",
|
|
37
|
+
]
|
|
38
|
+
default_url_template = (
|
|
39
|
+
"https://github.com/astral-sh/ty/releases/download/{version}/ty-{platform}.tar.gz"
|
|
40
|
+
)
|
|
41
|
+
default_url_platform_mapping = {
|
|
42
|
+
"linux_arm64": "aarch64-unknown-linux-musl",
|
|
43
|
+
"linux_x86_64": "x86_64-unknown-linux-musl",
|
|
44
|
+
"macos_arm64": "aarch64-apple-darwin",
|
|
45
|
+
"macos_x86_64": "x86_64-apple-darwin",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
skip = SkipOption("check")
|
|
49
|
+
args = ArgsListOption(example="--error-on-warning --output-format=concise")
|
|
50
|
+
config = FileOption(
|
|
51
|
+
default=None,
|
|
52
|
+
advanced=True,
|
|
53
|
+
help=softwrap(
|
|
54
|
+
"""
|
|
55
|
+
Path to a `ty.toml` file to use for configuration.
|
|
56
|
+
|
|
57
|
+
Setting this option disables `[ty].config_discovery`.
|
|
58
|
+
"""
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
config_discovery = BoolOption(
|
|
62
|
+
default=True,
|
|
63
|
+
advanced=True,
|
|
64
|
+
help=softwrap(
|
|
65
|
+
"""
|
|
66
|
+
If true, Pants will include relevant Ty config files during runs
|
|
67
|
+
(`ty.toml` and `pyproject.toml` containing `[tool.ty]`).
|
|
68
|
+
"""
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
_interpreter_constraints = StrListOption(
|
|
72
|
+
advanced=True,
|
|
73
|
+
default=["CPython>=3.8,<3.15"],
|
|
74
|
+
help="Python interpreter constraints for Ty.",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def generate_exe(self, plat: Platform) -> str:
|
|
78
|
+
return f"ty-{self.default_url_platform_mapping[plat.value]}/ty"
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def interpreter_constraints(self) -> InterpreterConstraints:
|
|
82
|
+
return InterpreterConstraints(self._interpreter_constraints)
|
|
83
|
+
|
|
84
|
+
def config_request(self) -> ConfigFilesRequest:
|
|
85
|
+
return ConfigFilesRequest(
|
|
86
|
+
specified=self.config,
|
|
87
|
+
specified_option_name=f"{self.options_scope}.config",
|
|
88
|
+
discovery=self.config_discovery,
|
|
89
|
+
check_existence=["ty.toml"],
|
|
90
|
+
check_content={"pyproject.toml": b"[tool.ty"},
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def rules() -> Iterable[Rule | UnionRule]:
|
|
95
|
+
return (
|
|
96
|
+
*collect_rules(),
|
|
97
|
+
*Ty.rules(),
|
|
98
|
+
UnionRule(ExportableTool, Ty),
|
|
99
|
+
)
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pants-ty
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Pants check backend for the Astral ty Python type checker.
|
|
5
|
+
Author: Vasile Razdalovschi
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/vrazdalovschi/pants-ty-plugin
|
|
8
|
+
Project-URL: Issues, https://github.com/vrazdalovschi/pants-ty-plugin/issues
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: pantsbuild.pants<2.32,>=2.31
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# pants-ty-plugin
|
|
21
|
+
|
|
22
|
+
`pants-ty-plugin` adds a Pants `check` backend for [Astral ty](https://docs.astral.sh/ty/).
|
|
23
|
+
|
|
24
|
+
It is designed for Pants `2.31.x` and currently supports Linux and macOS. The backend installs
|
|
25
|
+
`ty` as an external binary, then runs it with:
|
|
26
|
+
|
|
27
|
+
- a resolve-backed Python environment for third-party dependencies
|
|
28
|
+
- Pants source roots as `--extra-search-path` entries for first-party imports
|
|
29
|
+
|
|
30
|
+
That means `ty` can resolve imports that Pants already knows about.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- `pants check --only=ty ...`
|
|
35
|
+
- `skip_ty = true` on Python targets
|
|
36
|
+
- `ty.toml` discovery
|
|
37
|
+
- `[tool.ty]` discovery from `pyproject.toml`
|
|
38
|
+
- resolve-aware `--python`
|
|
39
|
+
- source-root-aware `--extra-search-path`
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
### Option 1: vendor the plugin into a private repo
|
|
44
|
+
|
|
45
|
+
Copy only the Python package files from `pants-plugins/pants_ty/` into your repo's
|
|
46
|
+
`pants-plugins/pants_ty/` directory:
|
|
47
|
+
|
|
48
|
+
- `__init__.py`
|
|
49
|
+
- `register.py`
|
|
50
|
+
- `rules.py`
|
|
51
|
+
- `skip_field.py`
|
|
52
|
+
- `subsystem.py`
|
|
53
|
+
|
|
54
|
+
Do not copy this plugin repo's development-only files:
|
|
55
|
+
|
|
56
|
+
- `pants-plugins/BUILD`
|
|
57
|
+
- `pants-plugins/pants_ty/BUILD`
|
|
58
|
+
- `pants-plugins/lock.txt`
|
|
59
|
+
- `tests/`
|
|
60
|
+
- this repo's `pants.toml`, `pyproject.toml`, or GitHub workflow files
|
|
61
|
+
|
|
62
|
+
Those files are only for developing and releasing `pants-ty-plugin` itself. A consuming repo
|
|
63
|
+
should use its own resolves, lockfiles, and test setup.
|
|
64
|
+
|
|
65
|
+
Then configure:
|
|
66
|
+
|
|
67
|
+
```toml
|
|
68
|
+
[GLOBAL]
|
|
69
|
+
pants_version = "2.31.0"
|
|
70
|
+
backend_packages = [
|
|
71
|
+
"pants.backend.python",
|
|
72
|
+
"pants_ty",
|
|
73
|
+
]
|
|
74
|
+
pythonpath = ["%(buildroot)s/pants-plugins"]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If you accidentally copy the dev `BUILD` files too, you may see an error like:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
UnrecognizedResolveNamesError: ... resolve ... pants-plugins
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
That means your consuming repo picked up this repo's internal development resolve. Remove the
|
|
84
|
+
copied `BUILD` files and keep only the plugin Python modules.
|
|
85
|
+
|
|
86
|
+
### Option 2: install as a published plugin
|
|
87
|
+
|
|
88
|
+
Once the package is published, use:
|
|
89
|
+
|
|
90
|
+
```toml
|
|
91
|
+
[GLOBAL]
|
|
92
|
+
plugins = ["pants-ty==0.1.0"]
|
|
93
|
+
backend_packages = [
|
|
94
|
+
"pants.backend.python",
|
|
95
|
+
"pants_ty",
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Configure
|
|
100
|
+
|
|
101
|
+
Create either `ty.toml` or add `[tool.ty]` to `pyproject.toml`.
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
|
|
105
|
+
```toml
|
|
106
|
+
[tool.ty]
|
|
107
|
+
exclude = [".pants.d", "dist"]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Pants exposes the plugin options under `[ty]`:
|
|
111
|
+
|
|
112
|
+
```toml
|
|
113
|
+
[ty]
|
|
114
|
+
args = ["--output-format=concise"]
|
|
115
|
+
config_discovery = true
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Useful commands:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pants help ty
|
|
122
|
+
pants check --only=ty ::
|
|
123
|
+
pants check --only=ty path/to/pkg::
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
To skip a target:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
python_sources(
|
|
130
|
+
name="lib",
|
|
131
|
+
skip_ty=True,
|
|
132
|
+
)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Development
|
|
136
|
+
|
|
137
|
+
This repo uses Pants to lint, test, and dogfood the plugin itself.
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
ruff check pants-plugins tests
|
|
141
|
+
pants test ::
|
|
142
|
+
pants check ::
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
To build a distributable wheel and sdist:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
python -m build
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Repository layout
|
|
152
|
+
|
|
153
|
+
- `pants-plugins/pants_ty`: plugin source
|
|
154
|
+
- `tests/pants_ty`: unit and integration tests
|
|
155
|
+
- `pants.toml`: local development config
|
|
156
|
+
- `pants.ci.toml`: CI-specific Pants settings
|
|
157
|
+
|
|
158
|
+
## Notes
|
|
159
|
+
|
|
160
|
+
- The Pants plugin API is not stable across minor versions. This repo currently targets
|
|
161
|
+
Pants `2.31.x`.
|
|
162
|
+
- The backend only resolves imports that Pants already knows through source roots and
|
|
163
|
+
target resolves.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
pants-plugins/pants_ty/__init__.py
|
|
5
|
+
pants-plugins/pants_ty/register.py
|
|
6
|
+
pants-plugins/pants_ty/rules.py
|
|
7
|
+
pants-plugins/pants_ty/skip_field.py
|
|
8
|
+
pants-plugins/pants_ty/subsystem.py
|
|
9
|
+
pants-plugins/pants_ty.egg-info/PKG-INFO
|
|
10
|
+
pants-plugins/pants_ty.egg-info/SOURCES.txt
|
|
11
|
+
pants-plugins/pants_ty.egg-info/dependency_links.txt
|
|
12
|
+
pants-plugins/pants_ty.egg-info/requires.txt
|
|
13
|
+
pants-plugins/pants_ty.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pantsbuild.pants<2.32,>=2.31
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pants_ty
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pants-ty"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A Pants check backend for the Astral ty Python type checker."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{name = "Vasile Razdalovschi"}]
|
|
14
|
+
dependencies = ["pantsbuild.pants>=2.31,<2.32"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Topic :: Software Development :: Build Tools",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Repository = "https://github.com/vrazdalovschi/pants-ty-plugin"
|
|
25
|
+
Issues = "https://github.com/vrazdalovschi/pants-ty-plugin/issues"
|
|
26
|
+
|
|
27
|
+
[tool.setuptools]
|
|
28
|
+
package-dir = {"" = "pants-plugins"}
|
|
29
|
+
|
|
30
|
+
[tool.setuptools.packages.find]
|
|
31
|
+
where = ["pants-plugins"]
|
|
32
|
+
include = ["pants_ty*"]
|
|
33
|
+
|
|
34
|
+
[tool.ruff]
|
|
35
|
+
line-length = 100
|
|
36
|
+
target-version = "py311"
|
|
37
|
+
exclude = [".git", ".pants.d", "build", "dist"]
|
pants_ty-0.1.0/setup.cfg
ADDED