1313# limitations under the License.
1414from dataclasses import dataclass
1515
16- from pants .backend .python .target_types import EntryPoint
1716from pants .backend .python .util_rules import pex , pex_from_targets
1817from pants .backend .python .util_rules .pex import (
1918 VenvPex ,
2019 VenvPexProcess ,
2120)
2221from pants .backend .python .util_rules .pex_from_targets import PexFromTargetsRequest
2322from 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
2626from pants .core .util_rules .source_files import SourceFiles , SourceFilesRequest
27- from pants .engine .addresses import Address
2827from pants .engine .fs import (
2928 CreateDigest ,
3029 Digest ,
3433)
3534from pants .engine .process import FallibleProcessResult , ProcessResult
3635from 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
4437from pants .util .logging import LogLevel
38+ from pants .util .strutil import strip_v2_chroot_path
4539
40+ from api_spec .subsystem import GenerateApiSpec , ValidateApiSpec
4641from 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 )
5845class APISpecFieldSet (FieldSet ):
5946 required_fields = (APISpecSourceField ,)
@@ -63,79 +50,39 @@ class APISpecFieldSet(FieldSet):
6350
6451class GenerateAPISpecViaFmtTargetsRequest (FmtTargetsRequest ):
6552 field_set_type = APISpecFieldSet
66- name = GENERATE_CMD
53+ tool_subsystem = GenerateApiSpec
54+ partitioner_type = PartitionerType .DEFAULT_SINGLE_PARTITION
6755
6856
6957class 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)
7867async 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)
173121async 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
252170def 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