Skip to content

Commit 11187ac

Browse files
committed
update pants-plugins/api_spec to pants 2.15
The Fmt/Lint plugin API changed in pants 2.15 It now requires a Subsystem with a SkipOption. I took advantage of this to consolidate the constants and all the address and pex request definitions in the Subsystem subclass. It now requires 2 rules instead of 1: to partition, then fmt/lint. That means the structure of the rule requests had to change slightly. The tests also had to account for the modified rules.
1 parent 784e337 commit 11187ac

3 files changed

Lines changed: 174 additions & 154 deletions

File tree

pants-plugins/api_spec/rules.py

Lines changed: 41 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,17 @@
1313
# limitations under the License.
1414
from dataclasses import dataclass
1515

16-
from pants.backend.python.target_types import EntryPoint
1716
from pants.backend.python.util_rules import pex, pex_from_targets
1817
from pants.backend.python.util_rules.pex import (
1918
VenvPex,
2019
VenvPexProcess,
2120
)
2221
from pants.backend.python.util_rules.pex_from_targets import PexFromTargetsRequest
2322
from pants.core.goals.fmt import FmtResult, FmtTargetsRequest
24-
from pants.core.goals.lint import LintResult, LintResults, LintTargetsRequest
25-
from pants.core.target_types import FileSourceField, ResourceSourceField
23+
from pants.core.goals.lint import LintResult, LintTargetsRequest
24+
from pants.core.util_rules.config_files import ConfigFiles, ConfigFilesRequest
25+
from pants.core.util_rules.partitions import PartitionerType
2626
from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
27-
from pants.engine.addresses import Address
2827
from pants.engine.fs import (
2928
CreateDigest,
3029
Digest,
@@ -34,26 +33,14 @@
3433
)
3534
from pants.engine.process import FallibleProcessResult, ProcessResult
3635
from pants.engine.rules import Get, MultiGet, collect_rules, rule
37-
from pants.engine.target import (
38-
FieldSet,
39-
SourcesField,
40-
TransitiveTargets,
41-
TransitiveTargetsRequest,
42-
)
43-
from pants.engine.unions import UnionRule
36+
from pants.engine.target import FieldSet
4437
from pants.util.logging import LogLevel
38+
from pants.util.strutil import strip_v2_chroot_path
4539

40+
from api_spec.subsystem import GenerateApiSpec, ValidateApiSpec
4641
from api_spec.target_types import APISpecSourceField
4742

4843

49-
# these constants are also used in the tests
50-
CMD_SOURCE_ROOT = "st2common"
51-
CMD_DIR = "st2common/st2common/cmd"
52-
CMD_MODULE = "st2common.cmd"
53-
GENERATE_CMD = "generate_api_spec"
54-
VALIDATE_CMD = "validate_api_spec"
55-
56-
5744
@dataclass(frozen=True)
5845
class APISpecFieldSet(FieldSet):
5946
required_fields = (APISpecSourceField,)
@@ -63,79 +50,39 @@ class APISpecFieldSet(FieldSet):
6350

6451
class GenerateAPISpecViaFmtTargetsRequest(FmtTargetsRequest):
6552
field_set_type = APISpecFieldSet
66-
name = GENERATE_CMD
53+
tool_subsystem = GenerateApiSpec
54+
partitioner_type = PartitionerType.DEFAULT_SINGLE_PARTITION
6755

6856

6957
class ValidateAPISpecRequest(LintTargetsRequest):
7058
field_set_type = APISpecFieldSet
71-
name = VALIDATE_CMD
59+
tool_subsystem = ValidateApiSpec
60+
partitioner_type = PartitionerType.DEFAULT_SINGLE_PARTITION
7261

7362

7463
@rule(
7564
desc="Update openapi.yaml with st2-generate-api-spec",
7665
level=LogLevel.DEBUG,
7766
)
7867
async def generate_api_spec_via_fmt(
79-
request: GenerateAPISpecViaFmtTargetsRequest,
68+
request: GenerateAPISpecViaFmtTargetsRequest.Batch,
69+
subsystem: GenerateApiSpec,
8070
) -> FmtResult:
8171
# There will only be one target+field_set, but we iterate
8272
# to satisfy how fmt expects that there could be more than one.
8373
# If there is more than one, they will all get the same contents.
8474

85-
# Find all the dependencies of our target
86-
transitive_targets = await Get(
87-
TransitiveTargets,
88-
TransitiveTargetsRequest(
89-
[field_set.address for field_set in request.field_sets]
90-
),
91-
)
92-
93-
dependency_files_get = Get(
94-
SourceFiles,
95-
SourceFilesRequest(
96-
sources_fields=[
97-
tgt.get(SourcesField) for tgt in transitive_targets.dependencies
98-
],
99-
for_sources_types=(FileSourceField, ResourceSourceField),
100-
),
101-
)
102-
103-
source_files_get = Get(
104-
SourceFiles,
105-
SourceFilesRequest(field_set.source for field_set in request.field_sets),
106-
)
75+
config_files_get = Get(ConfigFiles, ConfigFilesRequest, subsystem.config_request())
10776

10877
# actually generate it with an external script.
10978
# Generation cannot be inlined here because it needs to import the st2 code.
110-
pex_get = Get(
111-
VenvPex,
112-
PexFromTargetsRequest(
113-
[
114-
Address(
115-
CMD_DIR,
116-
target_name="cmd",
117-
relative_file_path=f"{GENERATE_CMD}.py",
118-
),
119-
],
120-
output_filename=f"{GENERATE_CMD}.pex",
121-
internal_only=True,
122-
main=EntryPoint.parse(f"{CMD_MODULE}.{GENERATE_CMD}:main"),
123-
),
124-
)
79+
pex_get = Get(VenvPex, PexFromTargetsRequest, subsystem.pex_request())
12580

126-
pex, dependency_files, source_files = await MultiGet(
127-
pex_get, dependency_files_get, source_files_get
128-
)
129-
130-
# If we were given an input digest from a previous formatter for the source files, then we
131-
# should use that input digest instead of the one we read from the filesystem.
132-
source_files_snapshot = (
133-
source_files.snapshot if request.snapshot is None else request.snapshot
134-
)
81+
config_files, pex = await MultiGet(config_files_get, pex_get)
13582

13683
input_digest = await Get(
13784
Digest,
138-
MergeDigests((dependency_files.snapshot.digest, source_files_snapshot.digest)),
85+
MergeDigests((config_files.snapshot.digest, request.snapshot.digest)),
13986
)
14087

14188
result = await Get(
@@ -144,87 +91,59 @@ async def generate_api_spec_via_fmt(
14491
pex,
14592
argv=(
14693
"--config-file",
147-
"conf/st2.dev.conf",
94+
subsystem.config_file,
14895
),
14996
input_digest=input_digest,
15097
description="Regenerating openapi.yaml api spec",
15198
level=LogLevel.DEBUG,
15299
),
153100
)
154101

155-
contents = [
156-
FileContent(
157-
f"{field_set.address.spec_path}/{field_set.source.value}",
158-
result.stdout,
159-
)
160-
for field_set in request.field_sets
161-
]
102+
contents = [FileContent(file, result.stdout) for file in request.files]
162103

163104
output_digest = await Get(Digest, CreateDigest(contents))
164105
output_snapshot = await Get(Snapshot, Digest, output_digest)
165-
# TODO: Drop result.stdout since we already wrote it to a file?
166-
return FmtResult.create(request, result, output_snapshot, strip_chroot_path=True)
106+
107+
return FmtResult(
108+
input=request.snapshot,
109+
output=output_snapshot,
110+
# Drop result.stdout since we already wrote it to a file
111+
stdout="",
112+
stderr=strip_v2_chroot_path(result.stderr),
113+
tool_name=request.tool_name,
114+
)
167115

168116

169117
@rule(
170118
desc="Validate openapi.yaml with st2-validate-api-spec",
171119
level=LogLevel.DEBUG,
172120
)
173121
async def validate_api_spec(
174-
request: ValidateAPISpecRequest,
175-
) -> LintResults:
122+
request: ValidateAPISpecRequest.Batch,
123+
subsystem: ValidateApiSpec,
124+
) -> LintResult:
176125
# There will only be one target+field_set, but we iterate
177126
# to satisfy how lint expects that there could be more than one.
178127
# If there is more than one, they will all get the same contents.
179128

180-
# Find all the dependencies of our target
181-
transitive_targets = await Get(
182-
TransitiveTargets,
183-
TransitiveTargetsRequest(
184-
[field_set.address for field_set in request.field_sets]
185-
),
186-
)
187-
188-
dependency_files_get = Get(
189-
SourceFiles,
190-
SourceFilesRequest(
191-
sources_fields=[
192-
tgt.get(SourcesField) for tgt in transitive_targets.dependencies
193-
],
194-
for_sources_types=(FileSourceField, ResourceSourceField),
195-
),
196-
)
197-
198129
source_files_get = Get(
199130
SourceFiles,
200-
SourceFilesRequest(field_set.source for field_set in request.field_sets),
131+
SourceFilesRequest(field_set.source for field_set in request.elements),
201132
)
202133

134+
config_files_get = Get(ConfigFiles, ConfigFilesRequest, subsystem.config_request())
135+
203136
# actually validate it with an external script.
204137
# Validation cannot be inlined here because it needs to import the st2 code.
205-
pex_get = Get(
206-
VenvPex,
207-
PexFromTargetsRequest(
208-
[
209-
Address(
210-
CMD_DIR,
211-
target_name="cmd",
212-
relative_file_path=f"{VALIDATE_CMD}.py",
213-
),
214-
],
215-
output_filename=f"{VALIDATE_CMD}.pex",
216-
internal_only=True,
217-
main=EntryPoint.parse(f"{CMD_MODULE}.{VALIDATE_CMD}:main"),
218-
),
219-
)
138+
pex_get = Get(VenvPex, PexFromTargetsRequest, subsystem.pex_request())
220139

221-
pex, dependency_files, source_files = await MultiGet(
222-
pex_get, dependency_files_get, source_files_get
140+
source_files, config_files, pex = await MultiGet(
141+
source_files_get, config_files_get, pex_get
223142
)
224143

225144
input_digest = await Get(
226145
Digest,
227-
MergeDigests((dependency_files.snapshot.digest, source_files.snapshot.digest)),
146+
MergeDigests((config_files.snapshot.digest, source_files.snapshot.digest)),
228147
)
229148

230149
process_result = await Get(
@@ -233,7 +152,7 @@ async def validate_api_spec(
233152
pex,
234153
argv=(
235154
"--config-file",
236-
"conf/st2.dev.conf",
155+
subsystem.config_file,
237156
# TODO: Uncomment these as part of a project to fix the (many) issues it identifies.
238157
# We can uncomment --validate-defs (and possibly --verbose) once the spec defs are valid.
239158
# "--validate-defs", # check for x-api-model in definitions
@@ -245,15 +164,14 @@ async def validate_api_spec(
245164
),
246165
)
247166

248-
result = LintResult.from_fallible_process_result(process_result)
249-
return LintResults([result], linter_name=request.name)
167+
return LintResult.create(request, process_result)
250168

251169

252170
def rules():
253171
return [
254172
*collect_rules(),
255-
UnionRule(FmtTargetsRequest, GenerateAPISpecViaFmtTargetsRequest),
256-
UnionRule(LintTargetsRequest, ValidateAPISpecRequest),
173+
*GenerateAPISpecViaFmtTargetsRequest.rules(),
174+
*ValidateAPISpecRequest.rules(),
257175
*pex.rules(),
258176
*pex_from_targets.rules(),
259177
]

0 commit comments

Comments
 (0)