gapic-generator 0.1.5 → 0.3.0
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 +55 -0
- data/lib/gapic/formatting_utils.rb +63 -12
- data/lib/gapic/generator/version.rb +1 -1
- data/lib/gapic/generators/base_generator.rb +0 -8
- data/lib/gapic/generators/default_generator.rb +13 -14
- data/lib/gapic/helpers/filepath_helper.rb +45 -0
- data/lib/gapic/helpers/namespace_helper.rb +51 -0
- data/lib/gapic/presenters.rb +44 -0
- data/{templates/default/helpers → lib/gapic}/presenters/enum_presenter.rb +19 -14
- data/{templates/default/helpers → lib/gapic}/presenters/enum_value_presenter.rb +19 -12
- data/lib/gapic/presenters/field_presenter.rb +154 -0
- data/lib/gapic/presenters/file_presenter.rb +59 -0
- data/lib/gapic/presenters/gem_presenter.rb +176 -0
- data/lib/gapic/presenters/message_presenter.rb +73 -0
- data/lib/gapic/presenters/method_presenter.rb +307 -0
- data/lib/gapic/presenters/package_presenter.rb +80 -0
- data/lib/gapic/presenters/resource_presenter.rb +99 -0
- data/lib/gapic/presenters/sample_presenter.rb +84 -0
- data/lib/gapic/presenters/service_presenter.rb +306 -0
- data/lib/gapic/resource_lookup.rb +23 -38
- data/lib/gapic/schema/api.rb +70 -0
- data/lib/gapic/schema/loader.rb +9 -2
- data/lib/gapic/schema/wrappers.rb +134 -24
- data/templates/default/gem/entrypoint.erb +8 -0
- data/templates/default/gem/gemspec.erb +2 -2
- data/templates/default/gem/readme.erb +17 -3
- data/templates/default/gem/rubocop.erb +13 -41
- data/templates/default/helpers/filepath_helper.rb +2 -21
- data/templates/default/helpers/namespace_helper.rb +2 -27
- data/templates/default/layouts/_ruby.erb +1 -3
- data/templates/default/lib/_package.erb +17 -0
- data/templates/default/lib/_service.erb +32 -0
- data/templates/default/package.erb +5 -5
- data/templates/default/service.erb +5 -7
- data/templates/default/service/_helpers.erb +3 -0
- data/templates/default/service/client/_client.erb +7 -17
- data/templates/default/service/client/_operations.erb +0 -4
- data/templates/default/service/client/_paths.erb +1 -0
- data/templates/default/service/client/method/def/_options_defaults.erb +1 -1
- data/templates/default/service/client/method/def/_response_normal.erb +1 -1
- data/templates/default/service/client/method/docs/_request_normal.erb +10 -5
- data/templates/default/service/client/method/docs/_request_streaming.erb +1 -1
- metadata +20 -15
- data/templates/default/helpers/presenter_helper.rb +0 -24
- data/templates/default/helpers/presenters/field_presenter.rb +0 -146
- data/templates/default/helpers/presenters/file_presenter.rb +0 -53
- data/templates/default/helpers/presenters/gem_presenter.rb +0 -140
- data/templates/default/helpers/presenters/message_presenter.rb +0 -66
- data/templates/default/helpers/presenters/method_presenter.rb +0 -293
- data/templates/default/helpers/presenters/package_presenter.rb +0 -65
- data/templates/default/helpers/presenters/resource_presenter.rb +0 -92
- data/templates/default/helpers/presenters/sample_presenter.rb +0 -74
- data/templates/default/helpers/presenters/service_presenter.rb +0 -276
- data/templates/default/service/client/_helpers.erb +0 -9
@@ -0,0 +1,307 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 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 "active_support/inflector"
|
18
|
+
require "gapic/path_template"
|
19
|
+
require "gapic/helpers/namespace_helper"
|
20
|
+
|
21
|
+
module Gapic
|
22
|
+
module Presenters
|
23
|
+
##
|
24
|
+
# A presenter for rpc methods.
|
25
|
+
#
|
26
|
+
class MethodPresenter
|
27
|
+
include Gapic::Helpers::NamespaceHelper
|
28
|
+
|
29
|
+
def initialize api, method
|
30
|
+
@api = api
|
31
|
+
@method = method
|
32
|
+
end
|
33
|
+
|
34
|
+
def service
|
35
|
+
ServicePresenter.new @api, @method.parent
|
36
|
+
end
|
37
|
+
|
38
|
+
def name
|
39
|
+
ActiveSupport::Inflector.underscore @method.name
|
40
|
+
end
|
41
|
+
|
42
|
+
def kind
|
43
|
+
if client_streaming?
|
44
|
+
if server_streaming?
|
45
|
+
:bidi
|
46
|
+
else
|
47
|
+
:client
|
48
|
+
end
|
49
|
+
elsif server_streaming?
|
50
|
+
:server
|
51
|
+
else
|
52
|
+
:normal
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def doc_description
|
57
|
+
@method.docs_leading_comments
|
58
|
+
end
|
59
|
+
|
60
|
+
def doc_response_type
|
61
|
+
ret = return_type
|
62
|
+
ret = "Gapic::Operation" if lro?
|
63
|
+
if server_streaming?
|
64
|
+
ret = "Enumerable<#{ret}>"
|
65
|
+
elsif paged?
|
66
|
+
paged_type = paged_response_type
|
67
|
+
paged_type = "Gapic::Operation" if paged_type == "Google::Longrunning::Operation"
|
68
|
+
ret = "Gapic::PagedEnumerable<#{paged_type}>"
|
69
|
+
end
|
70
|
+
ret
|
71
|
+
end
|
72
|
+
|
73
|
+
def arguments
|
74
|
+
arguments = @method.input.fields.reject(&:output_only?)
|
75
|
+
arguments.map { |arg| FieldPresenter.new @api, @method.input, arg }
|
76
|
+
end
|
77
|
+
|
78
|
+
def fields
|
79
|
+
@method.input.fields.map { |field| FieldPresenter.new @api, @method.input, field }
|
80
|
+
end
|
81
|
+
|
82
|
+
def fields_with_first_oneof
|
83
|
+
return fields if @method.input.oneof_decl.empty?
|
84
|
+
|
85
|
+
selected_fields = []
|
86
|
+
have_oneof = []
|
87
|
+
|
88
|
+
@method.input.fields.each do |field|
|
89
|
+
idx = field.oneof_index
|
90
|
+
selected_fields << field unless have_oneof.include? idx
|
91
|
+
have_oneof << idx
|
92
|
+
end
|
93
|
+
|
94
|
+
selected_fields.map { |field| FieldPresenter.new @api, @method.input, field }
|
95
|
+
end
|
96
|
+
|
97
|
+
def request_type
|
98
|
+
message_ruby_type @method.input
|
99
|
+
end
|
100
|
+
|
101
|
+
def return_type
|
102
|
+
message_ruby_type @method.output
|
103
|
+
end
|
104
|
+
|
105
|
+
def yields?
|
106
|
+
# Server streaming RCP calls are the only one that does not yield
|
107
|
+
!server_streaming?
|
108
|
+
end
|
109
|
+
|
110
|
+
def yield_doc_description
|
111
|
+
return "Register a callback to be run when an operation is done." if lro?
|
112
|
+
|
113
|
+
"Access the result along with the RPC operation"
|
114
|
+
end
|
115
|
+
|
116
|
+
def yield_params
|
117
|
+
if lro?
|
118
|
+
return [
|
119
|
+
OpenStruct.new(
|
120
|
+
name: "operation",
|
121
|
+
doc_types: "Gapic::Operation"
|
122
|
+
)
|
123
|
+
]
|
124
|
+
end
|
125
|
+
[
|
126
|
+
OpenStruct.new(
|
127
|
+
name: "result",
|
128
|
+
doc_types: return_type
|
129
|
+
),
|
130
|
+
OpenStruct.new(
|
131
|
+
name: "operation",
|
132
|
+
doc_types: "GRPC::ActiveCall::Operation"
|
133
|
+
)
|
134
|
+
]
|
135
|
+
end
|
136
|
+
|
137
|
+
# @api.incode samples and sample_configs are yaml configuration files such as
|
138
|
+
# speech_transcribe_sync_gcs.yaml
|
139
|
+
def samples
|
140
|
+
sample_configs = @api.incode_samples.select do |sample_config|
|
141
|
+
sample_config["service"] == @method.address[0...-1].join(".") &&
|
142
|
+
sample_config["rpc"] == @method.name
|
143
|
+
end
|
144
|
+
sample_configs.map { |sample_config| SamplePresenter.new @api, sample_config }
|
145
|
+
end
|
146
|
+
|
147
|
+
def lro?
|
148
|
+
return paged_response_type == "Google::Longrunning::Operation" if paged?
|
149
|
+
|
150
|
+
message_ruby_type(@method.output) == "Google::Longrunning::Operation"
|
151
|
+
end
|
152
|
+
|
153
|
+
def client_streaming?
|
154
|
+
@method.client_streaming
|
155
|
+
end
|
156
|
+
|
157
|
+
def server_streaming?
|
158
|
+
@method.server_streaming
|
159
|
+
end
|
160
|
+
|
161
|
+
def paged?
|
162
|
+
return false if server_streaming? # Cannot page a streaming response
|
163
|
+
|
164
|
+
# HACK(dazuma, 2020-04-06): Two specific RPCs should not be paged.
|
165
|
+
# This is an intentionally hard-coded exception (and a temporary one,
|
166
|
+
# to be removed when these methods no longer conform to AIP-4233.) For
|
167
|
+
# detailed information, see internal link go/actools-talent-pagination.
|
168
|
+
address = @method.address.join "."
|
169
|
+
return false if address == "google.cloud.talent.v4beta1.SearchProfiles"
|
170
|
+
return false if address == "google.cloud.talent.v4beta1.SearchJobs"
|
171
|
+
|
172
|
+
paged_request?(@method.input) && paged_response?(@method.output)
|
173
|
+
end
|
174
|
+
|
175
|
+
def paged_response_type
|
176
|
+
return nil unless paged_response? @method.output
|
177
|
+
|
178
|
+
repeated_field = @method.output.fields.find do |f|
|
179
|
+
f.label == Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED &&
|
180
|
+
f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
|
181
|
+
end
|
182
|
+
message_ruby_type repeated_field.message
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
#
|
187
|
+
# @return [Array<String>] The segment key names.
|
188
|
+
#
|
189
|
+
def routing_params
|
190
|
+
segments = Gapic::PathTemplate.parse method_path
|
191
|
+
segments.select { |s| s.is_a? Gapic::PathTemplate::Segment }.map(&:name)
|
192
|
+
end
|
193
|
+
|
194
|
+
def routing_params?
|
195
|
+
routing_params.any?
|
196
|
+
end
|
197
|
+
|
198
|
+
def grpc_service_config
|
199
|
+
if @api.grpc_service_config&.service_method_level_configs&.key?(service.grpc_full_name) &&
|
200
|
+
@api.grpc_service_config.service_method_level_configs[service.grpc_full_name]&.key?(grpc_method_name)
|
201
|
+
@api.grpc_service_config.service_method_level_configs[service.grpc_full_name][grpc_method_name]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def grpc_method_name
|
206
|
+
@method.name
|
207
|
+
end
|
208
|
+
|
209
|
+
protected
|
210
|
+
|
211
|
+
def message_ruby_type message
|
212
|
+
ruby_namespace @api, message.address.join(".")
|
213
|
+
end
|
214
|
+
|
215
|
+
def doc_types_for arg
|
216
|
+
if arg.message?
|
217
|
+
"#{message_ruby_type arg.message}, Hash"
|
218
|
+
elsif arg.enum?
|
219
|
+
# TODO: handle when arg message is nil and enum is the type
|
220
|
+
message_ruby_type arg.enum
|
221
|
+
else
|
222
|
+
case arg.type
|
223
|
+
when 1, 2 then "Float"
|
224
|
+
when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "Integer"
|
225
|
+
when 9, 12 then "String"
|
226
|
+
when 8 then "Boolean"
|
227
|
+
else
|
228
|
+
"Object"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def doc_desc_for arg
|
234
|
+
return nil if arg.docs.leading_comments.empty?
|
235
|
+
|
236
|
+
arg.docs.leading_comments
|
237
|
+
end
|
238
|
+
|
239
|
+
def default_value_for arg
|
240
|
+
if arg.message?
|
241
|
+
"{}"
|
242
|
+
elsif arg.enum?
|
243
|
+
# TODO: select the first non-0 enum value
|
244
|
+
# ":ENUM"
|
245
|
+
arg.enum.values.first
|
246
|
+
else
|
247
|
+
case arg.type
|
248
|
+
when 1, 2 then "3.14"
|
249
|
+
when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "42"
|
250
|
+
when 9, 12 then "\"hello world\""
|
251
|
+
when 8 then "true"
|
252
|
+
else
|
253
|
+
"Object"
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def method_path
|
259
|
+
return "" if @method.http.nil?
|
260
|
+
|
261
|
+
method = [
|
262
|
+
@method.http.get, @method.http.post, @method.http.put,
|
263
|
+
@method.http.patch, @method.http.delete
|
264
|
+
].find { |x| !x.empty? }
|
265
|
+
return method unless method.nil?
|
266
|
+
|
267
|
+
return @method.http.custom.path unless @method.http.custom.nil?
|
268
|
+
end
|
269
|
+
|
270
|
+
def paged_request? request
|
271
|
+
page_token = request.fields.find do |f|
|
272
|
+
f.name == "page_token" && f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
|
273
|
+
end
|
274
|
+
return false if page_token.nil?
|
275
|
+
|
276
|
+
page_size_types = [
|
277
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32,
|
278
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64
|
279
|
+
]
|
280
|
+
page_size = request.fields.find do |f|
|
281
|
+
f.name == "page_size" && page_size_types.include?(f.type)
|
282
|
+
end
|
283
|
+
return false if page_size.nil?
|
284
|
+
|
285
|
+
true
|
286
|
+
end
|
287
|
+
|
288
|
+
def paged_response? response
|
289
|
+
next_page_token = response.fields.find do |f|
|
290
|
+
f.name == "next_page_token" && f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
|
291
|
+
end
|
292
|
+
return false if next_page_token.nil?
|
293
|
+
|
294
|
+
repeated_field = response.fields.find do |f|
|
295
|
+
f.label == Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED &&
|
296
|
+
f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
|
297
|
+
end
|
298
|
+
return false if repeated_field.nil?
|
299
|
+
|
300
|
+
# We want to make sure the first repeated field is also has the lowest field number,
|
301
|
+
# but the google-protobuf gem sorts fields by number, so we lose the original order.
|
302
|
+
|
303
|
+
true
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 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 "active_support/inflector"
|
18
|
+
require "gapic/helpers/filepath_helper"
|
19
|
+
require "gapic/helpers/namespace_helper"
|
20
|
+
|
21
|
+
module Gapic
|
22
|
+
module Presenters
|
23
|
+
##
|
24
|
+
# A presenter for proto packages.
|
25
|
+
#
|
26
|
+
class PackagePresenter
|
27
|
+
include Gapic::Helpers::FilepathHelper
|
28
|
+
include Gapic::Helpers::NamespaceHelper
|
29
|
+
|
30
|
+
def initialize api, package
|
31
|
+
@api = api
|
32
|
+
@package = package
|
33
|
+
end
|
34
|
+
|
35
|
+
def gem
|
36
|
+
GemPresenter.new @api
|
37
|
+
end
|
38
|
+
|
39
|
+
def name
|
40
|
+
@package
|
41
|
+
end
|
42
|
+
|
43
|
+
def namespace
|
44
|
+
return services.first&.namespace if services.first&.namespace
|
45
|
+
ruby_namespace_for_address address
|
46
|
+
end
|
47
|
+
|
48
|
+
def parent_namespace
|
49
|
+
namespace.split("::")[0...-1].join("::")
|
50
|
+
end
|
51
|
+
|
52
|
+
def module_name
|
53
|
+
namespace.split("::").last
|
54
|
+
end
|
55
|
+
|
56
|
+
def services
|
57
|
+
@services ||= begin
|
58
|
+
files = @api.generate_files.select { |f| f.package == @package }
|
59
|
+
files.map(&:services).flatten.map { |s| ServicePresenter.new @api, s }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def address
|
64
|
+
@package.split "."
|
65
|
+
end
|
66
|
+
|
67
|
+
def package_require
|
68
|
+
ruby_file_path @api, namespace
|
69
|
+
end
|
70
|
+
|
71
|
+
def package_file_path
|
72
|
+
package_require + ".rb"
|
73
|
+
end
|
74
|
+
|
75
|
+
def empty?
|
76
|
+
services.empty?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 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/path_template"
|
18
|
+
require "ostruct"
|
19
|
+
require "active_support/inflector"
|
20
|
+
|
21
|
+
module Gapic
|
22
|
+
module Presenters
|
23
|
+
##
|
24
|
+
# A presenter for proto resources.
|
25
|
+
#
|
26
|
+
class ResourcePresenter
|
27
|
+
# @param resource [Google::Api::ResourceDescriptor]
|
28
|
+
def initialize resource
|
29
|
+
@resource = resource
|
30
|
+
|
31
|
+
@patterns = resource.pattern.map do |template|
|
32
|
+
segments = Gapic::PathTemplate.parse template
|
33
|
+
OpenStruct.new(
|
34
|
+
template: template,
|
35
|
+
segments: segments,
|
36
|
+
arguments: arguments_for(segments),
|
37
|
+
path_string: path_string_for(segments)
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
@patterns.each do |pattern|
|
42
|
+
# URI path template verification for expected proto resource usage
|
43
|
+
if named_arg_patterns? pattern.segments
|
44
|
+
raise ArgumentError, "only resources without named patterns are supported, " \
|
45
|
+
" not #{pattern.template}"
|
46
|
+
elsif positional_args? pattern.segments
|
47
|
+
raise ArgumentError, "only resources with named segments are supported, " \
|
48
|
+
" not #{pattern.template}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def name
|
54
|
+
@resource.type.split("/").delete_if(&:empty?).last
|
55
|
+
end
|
56
|
+
|
57
|
+
def type
|
58
|
+
@resource.type
|
59
|
+
end
|
60
|
+
|
61
|
+
def patterns
|
62
|
+
@patterns
|
63
|
+
end
|
64
|
+
|
65
|
+
def path_helper
|
66
|
+
"#{ActiveSupport::Inflector.underscore name}_path"
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def arguments_for segments
|
72
|
+
arg_segments(segments).map(&:name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def arg_segments segments
|
76
|
+
segments.select { |segment| segment.is_a? Gapic::PathTemplate::Segment }
|
77
|
+
end
|
78
|
+
|
79
|
+
def path_string_for segments
|
80
|
+
segments.map do |segment|
|
81
|
+
if segment.is_a? Gapic::PathTemplate::Segment
|
82
|
+
"\#{#{segment.name}}"
|
83
|
+
else
|
84
|
+
# Should be a String
|
85
|
+
segment
|
86
|
+
end
|
87
|
+
end.join
|
88
|
+
end
|
89
|
+
|
90
|
+
def positional_args? segments
|
91
|
+
arg_segments(segments).any?(&:positional?)
|
92
|
+
end
|
93
|
+
|
94
|
+
def named_arg_patterns? segments
|
95
|
+
arg_segments(segments).any?(&:pattern)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|