gapic-generator 0.45.1 → 0.45.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/gapic/formatting_utils.rb +2 -1
- data/lib/gapic/generator/version.rb +1 -1
- data/lib/gapic/model/api_metadata.rb +1 -1
- data/lib/gapic/presenters/method/compute_pagination_info.rb +392 -0
- data/lib/gapic/presenters/method_rest_presenter.rb +19 -6
- data/lib/gapic/presenters/snippet/expression_presenter.rb +26 -7
- data/templates/default/gem/gemfile.text.erb +1 -1
- metadata +5 -5
- data/lib/gapic/presenters/method/rest_pagination_info.rb +0 -255
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 271aec2d05b52adb5498c05c65461142789397a22d3b9a99d1d09f1559e8cf4f
|
4
|
+
data.tar.gz: 16e8bbbf90f2c0eb2174939cc7972fa37552cb807cfd24ecc0d74c9ed252a642
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e46aeb79a605c9395704b0cc14d4b8b540c34c119c9ee7d33178fc8d1a384d91fecfc42e92311e7197e36f9cec7cf21cb85e3a29850256643d348eae6571e8d2
|
7
|
+
data.tar.gz: 9f953a7d82a33f19a6309b6ca6abdf5da4b0f5bec294f6f1da8b0aadec47466f335a4df091c8021dd87a9596b0a310bdfa006fd617f03af8e167067a76712d47
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Release History for gapic-generator
|
2
2
|
|
3
|
+
### 0.45.3 / 2025-06-21
|
4
|
+
|
5
|
+
* Fix: correct pagination heuristic for Compute
|
6
|
+
* Fix: add libyaml to checks and configure for the prebuilt binary
|
7
|
+
* Fix: update Ruby prebuilt binary (version 3.4.3)
|
8
|
+
|
9
|
+
### 0.45.2 / 2025-06-04
|
10
|
+
|
11
|
+
* Fix: update Ruby prebuilt binary, version 3.4.3
|
12
|
+
|
3
13
|
### 0.45.1 / 2025-05-01
|
4
14
|
|
5
15
|
No significant changes
|
@@ -160,7 +160,7 @@ module Gapic
|
|
160
160
|
selector = setting[SELECTOR]
|
161
161
|
methods = service_config.apis.filter_map do |api|
|
162
162
|
# Removes API prefix and trailing period.
|
163
|
-
selector[api.name.length + 1..].downcase if selector.start_with? api.name
|
163
|
+
selector[(api.name.length + 1)..].downcase if selector.start_with? api.name
|
164
164
|
end
|
165
165
|
if !methods.nil? && setting.key?(AUTO_POPULATED_FIELDS)
|
166
166
|
@auto_populated_fields_by_method_name[methods.first] = setting[AUTO_POPULATED_FIELDS]
|
@@ -0,0 +1,392 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2021 Google LLC
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
require "gapic/model/model_error"
|
18
|
+
|
19
|
+
module Gapic
|
20
|
+
module Presenters
|
21
|
+
module Method
|
22
|
+
##
|
23
|
+
# Compute-specific pagination info determined from the proto method
|
24
|
+
#
|
25
|
+
# This implements the Compute-specific pagination heuristic
|
26
|
+
#
|
27
|
+
# The following steps are followed for this heuristic:
|
28
|
+
# 1. The method should not be server-streamed
|
29
|
+
# 2. The request should have a page token and page size fields
|
30
|
+
# 3. The response should have a next page token and contain a valid results field
|
31
|
+
#
|
32
|
+
# Now determining the valid results field is its own complicated sub-heuristic that should be run last.
|
33
|
+
# This sub-heuristic cannot end in "not paginated". It should either determine the results field or throw an error
|
34
|
+
#
|
35
|
+
# The following steps are followed for this sub-heuristic:
|
36
|
+
# 0. Check the exception dictionary. If the method is there as a key, use the value as the results field.
|
37
|
+
# 1. If there is exactly one map field, that field is the results field.
|
38
|
+
#
|
39
|
+
# NB: at this point the response contains either 0 or 2+ map fields
|
40
|
+
#
|
41
|
+
# 2. If there are no repeated fields there is no results field and we shall throw an error
|
42
|
+
# 3. If there is exactly one repeated field, that field is the results field.
|
43
|
+
# 4. If there are exactly 2 repeated fields, one is of message type, and the other is of type
|
44
|
+
# "String", the field of message type is the results field.
|
45
|
+
#
|
46
|
+
# At this point there are either 2 repeated fields in wrong configuration, or 3 or more repeated
|
47
|
+
# fields. The method should have been in the exception dictionary (see step 0).
|
48
|
+
# Since the method is NOT in the exception dictionary we should throw an error to prevent
|
49
|
+
# accidentally releasing a Compute library with incorrect pagination.
|
50
|
+
#
|
51
|
+
class ComputePaginationInfo
|
52
|
+
include Gapic::Helpers::NamespaceHelper
|
53
|
+
|
54
|
+
# @private Field name for Pagination Request page token
|
55
|
+
PAGE_TOKEN_NAME = "page_token"
|
56
|
+
private_constant :PAGE_TOKEN_NAME
|
57
|
+
# @private Field type for Pagination Request page token
|
58
|
+
PAGE_TOKEN_TYPE = :TYPE_STRING
|
59
|
+
private_constant :PAGE_TOKEN_TYPE
|
60
|
+
|
61
|
+
# @private Field names for Pagination Request page size
|
62
|
+
PAGE_SIZE_NAMES = ["page_size", "max_results"].freeze
|
63
|
+
private_constant :PAGE_SIZE_NAMES
|
64
|
+
# @private Field types for Pagination Request page size
|
65
|
+
PAGE_SIZE_TYPES = [:TYPE_UINT32, :TYPE_INT32].freeze
|
66
|
+
private_constant :PAGE_SIZE_TYPES
|
67
|
+
|
68
|
+
# @private Field name for Pagination Response next page token
|
69
|
+
NEXT_PAGE_TOKEN_NAME = "next_page_token"
|
70
|
+
private_constant :NEXT_PAGE_TOKEN_NAME
|
71
|
+
# @private Field type for Pagination Response next page token
|
72
|
+
NEXT_PAGE_TOKEN_TYPE = :TYPE_STRING
|
73
|
+
private_constant :NEXT_PAGE_TOKEN_TYPE
|
74
|
+
|
75
|
+
# @private A dictionary of special response messages of paginated methods and their repeated fields
|
76
|
+
# Curently contains only UsableSubnetworksAggregatedList which is a paginated field with 3 repeated fields,
|
77
|
+
# 2 of which are message-typed fields
|
78
|
+
REPEATED_FIELD_SPECIAL_DICTIONARY = {
|
79
|
+
"google.cloud.compute.v1.UsableSubnetworksAggregatedList" => "items",
|
80
|
+
"google.cloud.compute.v1beta.UsableSubnetworksAggregatedList" => "items"
|
81
|
+
}.freeze
|
82
|
+
private_constant :REPEATED_FIELD_SPECIAL_DICTIONARY
|
83
|
+
|
84
|
+
##
|
85
|
+
# @param proto_method [Gapic::Schema::Method] the method to derive pagination info from
|
86
|
+
# @param api [Gapic::Schema::Api]
|
87
|
+
#
|
88
|
+
def initialize proto_method, api
|
89
|
+
@api = api
|
90
|
+
@method_full_name = proto_method.full_name
|
91
|
+
@request = proto_method.input
|
92
|
+
@response = proto_method.output
|
93
|
+
@server_streaming = proto_method.server_streaming
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Whether the method should be generated as paged
|
98
|
+
#
|
99
|
+
# @return [Boolean]
|
100
|
+
def paged?
|
101
|
+
paged_candidate = !server_streaming? && paged_request? && paged_response_candidate?
|
102
|
+
|
103
|
+
# `paged_response?` can raise and should be evaluated last
|
104
|
+
paged_candidate && paged_response?
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Name of the request's field used for page size
|
109
|
+
# For Regapic can be either `page_size` or `max_results`
|
110
|
+
#
|
111
|
+
# @return [String, nil]
|
112
|
+
def request_page_size_name
|
113
|
+
request_page_size_field&.name
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Name of the repeated field in the response message
|
118
|
+
# For REST gapics can be either a vanilla repeated field or a map
|
119
|
+
#
|
120
|
+
# @return [String, nil]
|
121
|
+
def response_repeated_field_name
|
122
|
+
response_results_field&.name
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Whether the repeated field in the response message is a map
|
127
|
+
#
|
128
|
+
# @return [Boolean, nil]
|
129
|
+
def repeated_field_is_a_map?
|
130
|
+
response_results_field&.map?
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# Proto type of the repeated field in the response message
|
135
|
+
#
|
136
|
+
# @return [String, nil]
|
137
|
+
def paged_element_doc_type
|
138
|
+
return nil if response_results_field.nil?
|
139
|
+
field_paginated_elem_doc_type response_results_field
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
##
|
145
|
+
# Whether the underlying proto rpc is a server streaming rpc
|
146
|
+
#
|
147
|
+
# @return [Boolean]
|
148
|
+
attr_accessor :server_streaming
|
149
|
+
|
150
|
+
##
|
151
|
+
# Whether the underlying proto rpc is a server streaming rpc
|
152
|
+
#
|
153
|
+
# @return [Boolean]
|
154
|
+
def server_streaming?
|
155
|
+
@server_streaming
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
# Whether the request message for the REGAPIC rpc satisfies the criteria
|
160
|
+
# for the rpc to be classified and implemented as paged
|
161
|
+
#
|
162
|
+
# @return [Boolean]
|
163
|
+
def paged_request?
|
164
|
+
# Has a String page_token field which specifies the actual (next) page to retrieve.
|
165
|
+
# Has an int32 page_size or int32 max_results field
|
166
|
+
# which defines the maximum number of paginated resources to return in the response.
|
167
|
+
!request_page_token_field.nil? && !request_page_size_field.nil?
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# The field in the request that holds a page_token
|
172
|
+
#
|
173
|
+
# @return [Gapic::Schema::Field, nil]
|
174
|
+
def request_page_token_field
|
175
|
+
# Has a String page_token field which specifies the actual (next) page to retrieve.
|
176
|
+
@request_page_token_field ||= @request.fields.find do |f|
|
177
|
+
f.name == PAGE_TOKEN_NAME && f.type == PAGE_TOKEN_TYPE
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# The field in the request that holds a page_size
|
183
|
+
# For Regapic can have a name of either `page_size` or `max_results`
|
184
|
+
#
|
185
|
+
# @return [Gapic::Schema::Field, nil]
|
186
|
+
def request_page_size_field
|
187
|
+
@request_page_size_field ||=
|
188
|
+
begin
|
189
|
+
field = @request.fields.find do |f|
|
190
|
+
PAGE_SIZE_NAMES.include?(f.name) && PAGE_SIZE_TYPES.include?(f.type)
|
191
|
+
end
|
192
|
+
|
193
|
+
field
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
##
|
198
|
+
# Whether the response message for the REGAPIC rpc satisfies the criteria
|
199
|
+
# for the rpc to be classified and implemented as paged
|
200
|
+
#
|
201
|
+
# @return [Boolean]
|
202
|
+
def paged_response?
|
203
|
+
# Has the string next_page_token field to be used in the next request as
|
204
|
+
# page_token to retrieve the next page.
|
205
|
+
# Passes the heuristic for paginated response
|
206
|
+
# Order is important here, since paginated response heuristic can raise and should be evaluated last
|
207
|
+
paged_response_candidate? && !response_results_field.nil?
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# Whether the response message for the REGAPIC rpc satisfies the criteria
|
212
|
+
# to be a candidate for pagination. This is intentinally split from evaluating
|
213
|
+
# the paged response heuristic since that heuristic can raise.
|
214
|
+
#
|
215
|
+
# @return [Boolean]
|
216
|
+
def paged_response_candidate?
|
217
|
+
# Has the string next_page_token field to be used in the next request as
|
218
|
+
# page_token to retrieve the next page.
|
219
|
+
!response_next_page_token_field.nil?
|
220
|
+
end
|
221
|
+
|
222
|
+
##
|
223
|
+
# The field in the response that holds a next page_token
|
224
|
+
#
|
225
|
+
# @return [Gapic::Schema::Field, nil]
|
226
|
+
def response_next_page_token_field
|
227
|
+
# Has the string next_page_token field to be used in the next request as
|
228
|
+
# page_token to retrieve the next page.
|
229
|
+
@response_next_page_token_field ||= @response.fields.find do |f|
|
230
|
+
f.name == NEXT_PAGE_TOKEN_NAME && f.type == NEXT_PAGE_TOKEN_TYPE
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
|
235
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
236
|
+
# The heuristic in `response_results_field` would be more confusing if spread across several methods
|
237
|
+
|
238
|
+
##
|
239
|
+
# The field in the response that holds the results
|
240
|
+
# For Compute Regapic can be either a vanilla repeated field or a map
|
241
|
+
#
|
242
|
+
# @return [Gapic::Schema::Field, nil]
|
243
|
+
def response_results_field
|
244
|
+
# This sub-heuristic cannot end in "not paginated".
|
245
|
+
# It should either determine the results field or throw an error.
|
246
|
+
@response_results_field ||= begin
|
247
|
+
map_fields = @response.fields.find_all(&:map?)
|
248
|
+
repeated_fields = @response.fields.find_all do |f|
|
249
|
+
!f.map? && f.label == :LABEL_REPEATED
|
250
|
+
end
|
251
|
+
|
252
|
+
# The following steps are followed for this sub-heuristic:
|
253
|
+
# 0. Check the exception dictionary. If the method is there as key, use the value as the results field.
|
254
|
+
if REPEATED_FIELD_SPECIAL_DICTIONARY.key? @response.full_name
|
255
|
+
field_name = REPEATED_FIELD_SPECIAL_DICTIONARY[@response.full_name]
|
256
|
+
field = map_fields.find do |f|
|
257
|
+
f.name == field_name
|
258
|
+
end || repeated_fields.find do |f|
|
259
|
+
f.name == field_name
|
260
|
+
end
|
261
|
+
|
262
|
+
unless field
|
263
|
+
error_text = "A field of name \"#{field_name}\" is included in the special dictionary for " \
|
264
|
+
"the response type \"#{@response.full_name}\". However this field is not a map " \
|
265
|
+
"or repeated field. Failing, as the generator cannot continue."
|
266
|
+
|
267
|
+
raise ::Gapic::Model::ModelError, error_text
|
268
|
+
end
|
269
|
+
|
270
|
+
field
|
271
|
+
elsif map_fields.count == 1
|
272
|
+
# 1. If there is exactly one map field, that field is the results field.
|
273
|
+
map_fields.first
|
274
|
+
# NB: at this point the response contains either 0 or 2 map fields.
|
275
|
+
elsif repeated_fields.count.zero?
|
276
|
+
# 2. If there are no repeated fields there is no results field and we shall throw an error
|
277
|
+
error_text = "A response message \"#{@response.full_name}\" has a next page token field and " \
|
278
|
+
"is being evaluated as a candidate for pagination. However it has " \
|
279
|
+
"#{map_fields.count} (!= 1) map fields and no repeated fields. " \
|
280
|
+
"Failing, as the generator should not continue."
|
281
|
+
|
282
|
+
raise ::Gapic::Model::ModelError, error_text
|
283
|
+
elsif repeated_fields.count == 1
|
284
|
+
# 3. If there is exactly one repeated field, that field is the results field.
|
285
|
+
repeated_fields.first
|
286
|
+
elsif repeated_fields.count == 2
|
287
|
+
# 4. If there are exactly 2 repeated fields, one is of message type, and the other is of type
|
288
|
+
# "String", the field of message type is the results field.
|
289
|
+
pagination_field = repeated_fields.find(&:message?)
|
290
|
+
string_field = repeated_fields.find { |f| f.type == :TYPE_STRING }
|
291
|
+
|
292
|
+
unless pagination_field && string_field
|
293
|
+
# At this point if there are 2 repeated fields of different configuration, or 3 or more repeated
|
294
|
+
# fields the method should have been in the exception dictionary (see step 0).
|
295
|
+
error_text = "A response message \"#{@response.full_name}\" has a next page token " \
|
296
|
+
"field and is being evaluated as a candidate for pagination. However it should have " \
|
297
|
+
"a configuration of exactly 2 repeated fields, one is of message type, and the other " \
|
298
|
+
"of type \"String\". Failing, as the generator cannot continue. \n" \
|
299
|
+
"As a developer, please evaluate the message that fails this heuristic and either " \
|
300
|
+
"change the heuristic or add the message to the special dictionary."
|
301
|
+
|
302
|
+
raise ::Gapic::Model::ModelError, error_text
|
303
|
+
end
|
304
|
+
|
305
|
+
pagination_field
|
306
|
+
else
|
307
|
+
# At this point there are 3 or more repeated fields, and the method should have been in the
|
308
|
+
# exception dictionary (see step 0).
|
309
|
+
error_text = "A response message \"#{@response.full_name}\" has a next page token " \
|
310
|
+
"field and is being evaluated as a candidate for pagination. However it has " \
|
311
|
+
"#{repeated_fields.count} (>= 3) repeated fields, and not in the special dictionary " \
|
312
|
+
"for exceptions. Failing, as the generator cannot continue. \n" \
|
313
|
+
"As a developer, please evaluate the message that fails this heuristic and either " \
|
314
|
+
"change the heuristic or add the message to the special dictionary."
|
315
|
+
|
316
|
+
raise ::Gapic::Model::ModelError, error_text
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
322
|
+
|
323
|
+
# @private
|
324
|
+
FIELD_TYPE_MAPPING = {
|
325
|
+
TYPE_DOUBLE: "::Float",
|
326
|
+
TYPE_FLOAT: "::Float",
|
327
|
+
TYPE_INT64: "::Integer",
|
328
|
+
TYPE_UINT64: "::Integer",
|
329
|
+
TYPE_INT32: "::Integer",
|
330
|
+
TYPE_FIXED64: "::Integer",
|
331
|
+
TYPE_FIXED32: "::Integer",
|
332
|
+
TYPE_BOOL: "::Boolean",
|
333
|
+
TYPE_STRING: "::String",
|
334
|
+
TYPE_BYTES: "::String",
|
335
|
+
TYPE_UINT32: "::Integer",
|
336
|
+
TYPE_SFIXED32: "::Integer",
|
337
|
+
TYPE_SFIXED64: "::Integer",
|
338
|
+
TYPE_SINT32: "::Integer",
|
339
|
+
TYPE_SINT64: "::Integer"
|
340
|
+
}.freeze
|
341
|
+
private_constant :FIELD_TYPE_MAPPING
|
342
|
+
|
343
|
+
##
|
344
|
+
# A helper to get a Ruby doc-type for a paginated element.
|
345
|
+
#
|
346
|
+
# @param field [Gapic::Schema::Field]
|
347
|
+
#
|
348
|
+
# @return [String]
|
349
|
+
def field_paginated_elem_doc_type field
|
350
|
+
return field_paginated_elem_map_type field if field.map?
|
351
|
+
if field.message?
|
352
|
+
message_ruby_type field.message
|
353
|
+
elsif field.enum?
|
354
|
+
# TODO: handle when arg message is nil and enum is the type
|
355
|
+
message_ruby_type field.enum
|
356
|
+
else
|
357
|
+
FIELD_TYPE_MAPPING[field.type] || "::Object"
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
##
|
362
|
+
# A helper to get a Ruby doc-type for a proto map's paginated element.
|
363
|
+
#
|
364
|
+
# @param field [Gapic::Schema::Field]
|
365
|
+
#
|
366
|
+
# @return [String]
|
367
|
+
def field_paginated_elem_map_type field
|
368
|
+
key_field = field.map_key_field
|
369
|
+
value_field = field.map_val_field
|
370
|
+
|
371
|
+
if key_field && value_field
|
372
|
+
key_type = field_paginated_elem_doc_type key_field
|
373
|
+
value_type = field_paginated_elem_doc_type value_field
|
374
|
+
"#{key_type}, #{value_type}"
|
375
|
+
else
|
376
|
+
class_name
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
##
|
381
|
+
# A helper to get a Ruby type for a proto message.
|
382
|
+
#
|
383
|
+
# @param message [Gapic::Schema::Message]
|
384
|
+
#
|
385
|
+
# @return [String]
|
386
|
+
def message_ruby_type message
|
387
|
+
ruby_namespace @api, message.address.join(".")
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# See the License for the specific language governing permissions and
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
|
-
require "gapic/presenters/method/
|
17
|
+
require "gapic/presenters/method/compute_pagination_info"
|
18
18
|
|
19
19
|
module Gapic
|
20
20
|
module Presenters
|
@@ -22,9 +22,14 @@ module Gapic
|
|
22
22
|
# A presenter for rpc methods (REST submethods)
|
23
23
|
#
|
24
24
|
class MethodRestPresenter
|
25
|
-
# @return [Gapic::Presenters::Method::
|
25
|
+
# @return [Gapic::Presenters::Method::ComputePaginationInfo] Special pagination presenter for Compute
|
26
26
|
attr_reader :compute_pagination
|
27
27
|
|
28
|
+
##
|
29
|
+
# Presenters for HTTP bindings, used to check whether this method should be generated in REST client
|
30
|
+
#
|
31
|
+
# @return [Array<Gapic::Presenters::Method::HttpBindingsPresenter>]
|
32
|
+
#
|
28
33
|
attr_reader :http_bindings
|
29
34
|
|
30
35
|
# @return [String] String representation of this presenter type.
|
@@ -39,7 +44,7 @@ module Gapic
|
|
39
44
|
@http_bindings = main_method.http_bindings
|
40
45
|
@compute_pagination =
|
41
46
|
if @main_method.service.special_compute_behavior?
|
42
|
-
Gapic::Presenters::Method::
|
47
|
+
Gapic::Presenters::Method::ComputePaginationInfo.new main_method.method, api
|
43
48
|
end
|
44
49
|
@type = "method"
|
45
50
|
end
|
@@ -54,7 +59,7 @@ module Gapic
|
|
54
59
|
end
|
55
60
|
|
56
61
|
##
|
57
|
-
# Method name
|
62
|
+
# Method's name
|
58
63
|
#
|
59
64
|
# @return [String]
|
60
65
|
#
|
@@ -62,8 +67,11 @@ module Gapic
|
|
62
67
|
@main_method.name
|
63
68
|
end
|
64
69
|
|
70
|
+
##
|
65
71
|
# Fully qualified proto name of the method (namespace.PascalCase)
|
72
|
+
#
|
66
73
|
# @return [String]
|
74
|
+
#
|
67
75
|
def grpc_full_name
|
68
76
|
@main_method.grpc.full_name
|
69
77
|
end
|
@@ -103,7 +111,10 @@ module Gapic
|
|
103
111
|
end
|
104
112
|
|
105
113
|
##
|
106
|
-
#
|
114
|
+
# Name of the repeated field in paginated responses
|
115
|
+
# For Compute the pagination is different from GRPC and cannot be looked up in GRPC method presenter
|
116
|
+
#
|
117
|
+
# @return [String]
|
107
118
|
#
|
108
119
|
def paged_response_repeated_field_name
|
109
120
|
if compute_pagination
|
@@ -168,7 +179,9 @@ module Gapic
|
|
168
179
|
end
|
169
180
|
|
170
181
|
##
|
171
|
-
#
|
182
|
+
# Whether the method is marked as deprecated.
|
183
|
+
#
|
184
|
+
# @return [Boolean]
|
172
185
|
#
|
173
186
|
def is_deprecated?
|
174
187
|
@main_method.is_deprecated?
|
@@ -95,7 +95,7 @@ module Gapic
|
|
95
95
|
|
96
96
|
def render_complex proto, json
|
97
97
|
lines = ["{"]
|
98
|
-
proto.each do |key, value_expr|
|
98
|
+
proto.sort_by { |key, _| key.to_s }.each do |key, value_expr|
|
99
99
|
value_presenter = ExpressionPresenter.new value_expr, json[key]
|
100
100
|
value_lines = value_presenter.render_lines
|
101
101
|
next unless value_lines
|
@@ -107,9 +107,12 @@ module Gapic
|
|
107
107
|
end
|
108
108
|
|
109
109
|
def render_list proto, json
|
110
|
+
exprs = proto.map.with_index do |item, index|
|
111
|
+
ExpressionPresenter.new item, json[index]
|
112
|
+
end
|
113
|
+
|
110
114
|
lines = ["["]
|
111
|
-
|
112
|
-
expr = ExpressionPresenter.new item, json[index]
|
115
|
+
exprs.sort_by(&:render).each do |expr|
|
113
116
|
value_lines = expr.render_lines
|
114
117
|
lines[lines.size - 1] = "#{lines.last}," if lines.size > 1
|
115
118
|
lines += value_lines.map { |line| " #{line}" }
|
@@ -118,17 +121,33 @@ module Gapic
|
|
118
121
|
end
|
119
122
|
|
120
123
|
def render_map proto, json
|
124
|
+
key_to_kvlines = get_key_to_kvlines proto, json
|
125
|
+
|
121
126
|
lines = ["{"]
|
122
|
-
|
123
|
-
key_lines =
|
124
|
-
value_lines =
|
125
|
-
next unless key_lines && value_lines
|
127
|
+
key_to_kvlines.sort_by { |key, _| key }.each do |_, key_val_lines|
|
128
|
+
key_lines = key_val_lines[0]
|
129
|
+
value_lines = key_val_lines[1]
|
126
130
|
elem_lines = key_lines[0..-2] + ["#{key_lines.last} => #{value_lines.first}"] + value_lines[1..]
|
127
131
|
lines[lines.size - 1] = "#{lines.last}," if lines.size > 1
|
128
132
|
lines += elem_lines.map { |line| " #{line}" }
|
129
133
|
end
|
130
134
|
lines + ["}"]
|
131
135
|
end
|
136
|
+
|
137
|
+
# Helper method to render_map.
|
138
|
+
# Returns a map from a key rendered as a string
|
139
|
+
# to the array of key and value rendered as lines.
|
140
|
+
def get_key_to_kvlines proto, json
|
141
|
+
key_to_kvlines = {}
|
142
|
+
proto.keys.zip(proto.values).each_with_index do |(key, value), index|
|
143
|
+
key_expr = ExpressionPresenter.new key, json["keys"][index]
|
144
|
+
value_expr = ExpressionPresenter.new value, json["values"][index]
|
145
|
+
next unless key_expr.render_lines && value_expr.render_lines
|
146
|
+
|
147
|
+
key_to_kvlines[key_expr.render] = [key_expr.render_lines, value_expr.render_lines]
|
148
|
+
end
|
149
|
+
key_to_kvlines
|
150
|
+
end
|
132
151
|
end
|
133
152
|
end
|
134
153
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gapic-generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.45.
|
4
|
+
version: 0.45.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernest Landrito
|
@@ -87,14 +87,14 @@ dependencies:
|
|
87
87
|
requirements:
|
88
88
|
- - "~>"
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: 1.31.
|
90
|
+
version: 1.31.1
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: 1.31.
|
97
|
+
version: 1.31.1
|
98
98
|
email:
|
99
99
|
- landrito@google.com
|
100
100
|
- quartzmo@gmail.com
|
@@ -167,8 +167,8 @@ files:
|
|
167
167
|
- lib/gapic/presenters/gem_presenter.rb
|
168
168
|
- lib/gapic/presenters/grpc_service_config_presenter.rb
|
169
169
|
- lib/gapic/presenters/message_presenter.rb
|
170
|
+
- lib/gapic/presenters/method/compute_pagination_info.rb
|
170
171
|
- lib/gapic/presenters/method/http_binding_presenter.rb
|
171
|
-
- lib/gapic/presenters/method/rest_pagination_info.rb
|
172
172
|
- lib/gapic/presenters/method_presenter.rb
|
173
173
|
- lib/gapic/presenters/method_rest_presenter.rb
|
174
174
|
- lib/gapic/presenters/package_presenter.rb
|
@@ -365,7 +365,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
365
365
|
- !ruby/object:Gem::Version
|
366
366
|
version: '0'
|
367
367
|
requirements: []
|
368
|
-
rubygems_version: 3.6.
|
368
|
+
rubygems_version: 3.6.9
|
369
369
|
specification_version: 4
|
370
370
|
summary: An API Client Generator for Ruby in Ruby!
|
371
371
|
test_files: []
|
@@ -1,255 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright 2021 Google LLC
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# https://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
|
17
|
-
module Gapic
|
18
|
-
module Presenters
|
19
|
-
module Method
|
20
|
-
##
|
21
|
-
# Pagination info determined from the proto method
|
22
|
-
#
|
23
|
-
class RestPaginationInfo
|
24
|
-
include Gapic::Helpers::NamespaceHelper
|
25
|
-
##
|
26
|
-
# @param proto_method [Gapic::Schema::Method] the method to derive pagination info from
|
27
|
-
# @param api [Gapic::Schema::Api]
|
28
|
-
#
|
29
|
-
def initialize proto_method, api
|
30
|
-
@api = api
|
31
|
-
@request = proto_method.input
|
32
|
-
@response = proto_method.output
|
33
|
-
@server_streaming = proto_method.server_streaming
|
34
|
-
end
|
35
|
-
|
36
|
-
##
|
37
|
-
# Whether the method should be generated as paged
|
38
|
-
#
|
39
|
-
# @return [Boolean]
|
40
|
-
def paged?
|
41
|
-
!server_streaming? && paged_request? && paged_response?
|
42
|
-
end
|
43
|
-
|
44
|
-
##
|
45
|
-
# Name of the request's field used for page size
|
46
|
-
# For Regapic can be either `page_size` or `max_results`
|
47
|
-
#
|
48
|
-
# @return [String, nil]
|
49
|
-
def request_page_size_name
|
50
|
-
request_page_size_field&.name
|
51
|
-
end
|
52
|
-
|
53
|
-
##
|
54
|
-
# Name of the repeated field in the response message
|
55
|
-
# For REST gapics can be either a vanilla repeated field or a map
|
56
|
-
#
|
57
|
-
# @return [String, nil]
|
58
|
-
def response_repeated_field_name
|
59
|
-
response_results_field&.name
|
60
|
-
end
|
61
|
-
|
62
|
-
##
|
63
|
-
# Whether the repeated field in the response message is a map
|
64
|
-
#
|
65
|
-
# @return [Boolean, nil]
|
66
|
-
def repeated_field_is_a_map?
|
67
|
-
response_results_field&.map?
|
68
|
-
end
|
69
|
-
|
70
|
-
##
|
71
|
-
# Proto type of the repeated field in the response message
|
72
|
-
#
|
73
|
-
# @return [String, nil]
|
74
|
-
def paged_element_doc_type
|
75
|
-
return nil if response_results_field.nil?
|
76
|
-
field_paginated_elem_doc_type response_results_field
|
77
|
-
end
|
78
|
-
|
79
|
-
private
|
80
|
-
|
81
|
-
# Whether the underlying proto rpc is a server streaming rpc
|
82
|
-
# @return [Boolean]
|
83
|
-
attr_accessor :server_streaming
|
84
|
-
|
85
|
-
##
|
86
|
-
# Whether the underlying proto rpc is a server streaming rpc
|
87
|
-
#
|
88
|
-
# @return [Boolean]
|
89
|
-
def server_streaming?
|
90
|
-
@server_streaming
|
91
|
-
end
|
92
|
-
|
93
|
-
##
|
94
|
-
# Whether the request message for the REGAPIC rpc satisfies the criteria
|
95
|
-
# for the rpc to be classified and implemented as paged
|
96
|
-
#
|
97
|
-
# @return [Boolean]
|
98
|
-
def paged_request?
|
99
|
-
# Has a String page_token field which specifies the actual (next) page to retrieve.
|
100
|
-
# Has an int32 page_size or int32 max_results field
|
101
|
-
# which defines the maximum number of paginated resources to return in the response.
|
102
|
-
!request_page_token_field.nil? && !request_page_size_field.nil?
|
103
|
-
end
|
104
|
-
|
105
|
-
##
|
106
|
-
# The field in the request that holds a page_token
|
107
|
-
#
|
108
|
-
# @return[Gapic::Schema::Field, nil]
|
109
|
-
def request_page_token_field
|
110
|
-
# Has a String page_token field which specifies the actual (next) page to retrieve.
|
111
|
-
@request_page_token_field ||= @request.fields.find do |f|
|
112
|
-
f.name == "page_token" && f.type == :TYPE_STRING
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
##
|
117
|
-
# The field in the request that holds a page_size
|
118
|
-
# For Regapic can have a name of either `page_size` or `max_results`
|
119
|
-
#
|
120
|
-
# @return[Gapic::Schema::Field, nil]
|
121
|
-
def request_page_size_field
|
122
|
-
@request_page_size_field ||=
|
123
|
-
begin
|
124
|
-
page_size_names = ["page_size", "max_results"]
|
125
|
-
|
126
|
-
# Has the int32 page_size or int32 max_results field
|
127
|
-
# which defines the maximum number of paginated resources to return in the response.
|
128
|
-
page_size_types = [:TYPE_UINT32, :TYPE_INT32]
|
129
|
-
|
130
|
-
field = @request.fields.find do |f|
|
131
|
-
page_size_names.include?(f.name) && page_size_types.include?(f.type)
|
132
|
-
end
|
133
|
-
|
134
|
-
field
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
##
|
139
|
-
# Whether the response message for the REGAPIC rpc satisfies the criteria
|
140
|
-
# for the rpc to be classified and implemented as paged
|
141
|
-
#
|
142
|
-
# @return [Boolean]
|
143
|
-
def paged_response?
|
144
|
-
# Has the string next_page_token field to be used in the next request as page_token to retrieve the next page.
|
145
|
-
# Has only one repeated or map<string, ?> field containing a list of paginated resources.
|
146
|
-
!response_next_page_token_field.nil? && !response_results_field.nil?
|
147
|
-
end
|
148
|
-
|
149
|
-
##
|
150
|
-
# The field in the response that holds a next page_token
|
151
|
-
#
|
152
|
-
# @return[Gapic::Schema::Field, nil]
|
153
|
-
def response_next_page_token_field
|
154
|
-
# Has the string next_page_token field to be used in the next request as page_token to retrieve the next page.
|
155
|
-
@response_next_page_token_field ||= @response.fields.find do |f|
|
156
|
-
f.name == "next_page_token" && f.type == :TYPE_STRING
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
##
|
161
|
-
# The field in the response that holds the results
|
162
|
-
# For Regapic can be either a vanilla repeated field or a map
|
163
|
-
#
|
164
|
-
# @return [Gapic::Schema::Field, nil]
|
165
|
-
def response_results_field
|
166
|
-
@response_results_field ||= begin
|
167
|
-
map_fields = @response.fields.find_all(&:map?)
|
168
|
-
repeated_fields = @response.fields.find_all do |f|
|
169
|
-
!f.map? && f.label == :LABEL_REPEATED
|
170
|
-
end
|
171
|
-
|
172
|
-
if map_fields.count == 1
|
173
|
-
# If the response message has only one map<string, ?> field
|
174
|
-
# treat it as the one with paginated resources (i.e. ignore the repeated fields if any).
|
175
|
-
map_fields.first
|
176
|
-
elsif repeated_fields.count == 1 && map_fields.empty?
|
177
|
-
# If the response message contains only one repeated field,
|
178
|
-
# treat that field as the one containing the paginated resources.
|
179
|
-
repeated_fields.first
|
180
|
-
end
|
181
|
-
# If the response message contains more than one repeated field or does not have repeated fields at all
|
182
|
-
# but has more than one map<string, ?> field, do not generate any paginated methods for such rpc.
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
# @private
|
187
|
-
FIELD_TYPE_MAPPING = {
|
188
|
-
TYPE_DOUBLE: "::Float",
|
189
|
-
TYPE_FLOAT: "::Float",
|
190
|
-
TYPE_INT64: "::Integer",
|
191
|
-
TYPE_UINT64: "::Integer",
|
192
|
-
TYPE_INT32: "::Integer",
|
193
|
-
TYPE_FIXED64: "::Integer",
|
194
|
-
TYPE_FIXED32: "::Integer",
|
195
|
-
TYPE_BOOL: "::Boolean",
|
196
|
-
TYPE_STRING: "::String",
|
197
|
-
TYPE_BYTES: "::String",
|
198
|
-
TYPE_UINT32: "::Integer",
|
199
|
-
TYPE_SFIXED32: "::Integer",
|
200
|
-
TYPE_SFIXED64: "::Integer",
|
201
|
-
TYPE_SINT32: "::Integer",
|
202
|
-
TYPE_SINT64: "::Integer"
|
203
|
-
}.freeze
|
204
|
-
private_constant :FIELD_TYPE_MAPPING
|
205
|
-
|
206
|
-
##
|
207
|
-
# A helper to get a Ruby doc-type for a paginated element.
|
208
|
-
#
|
209
|
-
# @param field [Gapic::Schema::Field]
|
210
|
-
#
|
211
|
-
# @return [String]
|
212
|
-
def field_paginated_elem_doc_type field
|
213
|
-
return field_paginated_elem_map_type field if field.map?
|
214
|
-
if field.message?
|
215
|
-
message_ruby_type field.message
|
216
|
-
elsif field.enum?
|
217
|
-
# TODO: handle when arg message is nil and enum is the type
|
218
|
-
message_ruby_type field.enum
|
219
|
-
else
|
220
|
-
FIELD_TYPE_MAPPING[field.type] || "::Object"
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
##
|
225
|
-
# A helper to get a Ruby doc-type for a proto map's paginated element.
|
226
|
-
#
|
227
|
-
# @param field [Gapic::Schema::Field]
|
228
|
-
#
|
229
|
-
# @return [String]
|
230
|
-
def field_paginated_elem_map_type field
|
231
|
-
key_field = field.map_key_field
|
232
|
-
value_field = field.map_val_field
|
233
|
-
|
234
|
-
if key_field && value_field
|
235
|
-
key_type = field_paginated_elem_doc_type key_field
|
236
|
-
value_type = field_paginated_elem_doc_type value_field
|
237
|
-
"#{key_type}, #{value_type}"
|
238
|
-
else
|
239
|
-
class_name
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
##
|
244
|
-
# A helper to get a Ruby type for a proto message.
|
245
|
-
#
|
246
|
-
# @param message [Gapic::Schema::Message]
|
247
|
-
#
|
248
|
-
# @return [String]
|
249
|
-
def message_ruby_type message
|
250
|
-
ruby_namespace @api, message.address.join(".")
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|