gapic-generator 0.1.7 → 0.2.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/lib/gapic/formatting_utils.rb +9 -4
  4. data/lib/gapic/generator/version.rb +1 -1
  5. data/lib/gapic/generators/base_generator.rb +0 -8
  6. data/lib/gapic/generators/default_generator.rb +2 -4
  7. data/lib/gapic/helpers/filepath_helper.rb +45 -0
  8. data/lib/gapic/helpers/namespace_helper.rb +51 -0
  9. data/lib/gapic/presenters.rb +44 -0
  10. data/{templates/default/helpers → lib/gapic}/presenters/enum_presenter.rb +19 -14
  11. data/{templates/default/helpers → lib/gapic}/presenters/enum_value_presenter.rb +19 -12
  12. data/lib/gapic/presenters/field_presenter.rb +154 -0
  13. data/lib/gapic/presenters/file_presenter.rb +59 -0
  14. data/lib/gapic/presenters/gem_presenter.rb +170 -0
  15. data/lib/gapic/presenters/message_presenter.rb +73 -0
  16. data/lib/gapic/presenters/method_presenter.rb +298 -0
  17. data/lib/gapic/presenters/package_presenter.rb +72 -0
  18. data/lib/gapic/presenters/resource_presenter.rb +99 -0
  19. data/lib/gapic/presenters/sample_presenter.rb +84 -0
  20. data/lib/gapic/presenters/service_presenter.rb +297 -0
  21. data/lib/gapic/resource_lookup.rb +8 -1
  22. data/lib/gapic/schema/api.rb +16 -0
  23. data/lib/gapic/schema/wrappers.rb +9 -2
  24. data/templates/default/gem/readme.erb +2 -2
  25. data/templates/default/helpers/filepath_helper.rb +2 -21
  26. data/templates/default/helpers/namespace_helper.rb +2 -27
  27. data/templates/default/layouts/_ruby.erb +1 -3
  28. data/templates/default/service/client/_client.erb +7 -1
  29. metadata +16 -14
  30. data/templates/default/helpers/presenter_helper.rb +0 -24
  31. data/templates/default/helpers/presenters/field_presenter.rb +0 -146
  32. data/templates/default/helpers/presenters/file_presenter.rb +0 -53
  33. data/templates/default/helpers/presenters/gem_presenter.rb +0 -140
  34. data/templates/default/helpers/presenters/message_presenter.rb +0 -66
  35. data/templates/default/helpers/presenters/method_presenter.rb +0 -293
  36. data/templates/default/helpers/presenters/package_presenter.rb +0 -65
  37. data/templates/default/helpers/presenters/resource_presenter.rb +0 -92
  38. data/templates/default/helpers/presenters/sample_presenter.rb +0 -74
  39. data/templates/default/helpers/presenters/service_presenter.rb +0 -276
@@ -0,0 +1,59 @@
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 "gapic/helpers/namespace_helper"
18
+
19
+ module Gapic
20
+ module Presenters
21
+ ##
22
+ # A presenter for proto files.
23
+ #
24
+ class FilePresenter
25
+ include Gapic::Helpers::NamespaceHelper
26
+
27
+ # @param file [Gapic::Schema::File] the file to present
28
+ def initialize api, file
29
+ @api = api
30
+ @file = file
31
+ end
32
+
33
+ def name
34
+ @file.name
35
+ end
36
+
37
+ def address
38
+ @file.address
39
+ end
40
+
41
+ def namespace
42
+ return @file.ruby_package if @file.ruby_package.present?
43
+ ruby_namespace_for_address address
44
+ end
45
+
46
+ def messages
47
+ @messages ||= @file.messages.map { |m| MessagePresenter.new @api, m }
48
+ end
49
+
50
+ def enums
51
+ @enums ||= @file.enums.map { |e| EnumPresenter.new e }
52
+ end
53
+
54
+ def docs_file_path
55
+ @file.name.gsub ".proto", ".rb"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,170 @@
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/helpers/filepath_helper"
18
+ require "gapic/helpers/namespace_helper"
19
+
20
+ module Gapic
21
+ module Presenters
22
+ ##
23
+ # A presenter for gems.
24
+ #
25
+ class GemPresenter
26
+ include Gapic::Helpers::FilepathHelper
27
+ include Gapic::Helpers::NamespaceHelper
28
+
29
+ def initialize api
30
+ @api = api
31
+ end
32
+
33
+ def packages
34
+ @packages ||= begin
35
+ packages = @api.generate_files.map(&:package).uniq.sort
36
+ packages.map { |p| PackagePresenter.new @api, p }.delete_if(&:empty?)
37
+ end
38
+ end
39
+
40
+ def services
41
+ @services ||= begin
42
+ files = @api.generate_files
43
+ files.map(&:services).flatten.map { |s| ServicePresenter.new @api, s }
44
+ end
45
+ end
46
+
47
+ def proto_files
48
+ @proto_files ||= begin
49
+ files = @api.files
50
+ files = files.reject { |f| blacklist_protos.include? f.name }
51
+ files = files.reject { |f| f.messages.empty? && f.enums.empty? }
52
+ files.map { |f| FilePresenter.new @api, f }
53
+ end
54
+ end
55
+
56
+ def address
57
+ name.split("-").map(&:camelize)
58
+ end
59
+
60
+ def name
61
+ gem_config :name
62
+ end
63
+
64
+ def namespace
65
+ gem_config(:namespace) ||
66
+ fix_namespace(@api, name.split("-").map(&:camelize).join("::"))
67
+ end
68
+
69
+ def title
70
+ gem_config(:title) ||
71
+ namespace.split("::").join(" ")
72
+ end
73
+
74
+ def version
75
+ gem_config(:version) ||
76
+ "0.0.1"
77
+ end
78
+
79
+ def version_require
80
+ ruby_file_path @api, version_name_full
81
+ end
82
+
83
+ def version_file_path
84
+ "#{version_require}.rb"
85
+ end
86
+
87
+ def version_name_full
88
+ "#{namespace}::VERSION"
89
+ end
90
+
91
+ def authors
92
+ gem_config(:authors) ||
93
+ ["Google LLC"]
94
+ end
95
+
96
+ def email
97
+ gem_config(:email) ||
98
+ "googleapis-packages@google.com"
99
+ end
100
+
101
+ def description
102
+ gem_config(:description) ||
103
+ "#{name} is the official client library for the #{title} API."
104
+ end
105
+
106
+ def summary
107
+ gem_config(:summary) ||
108
+ "API Client library for the #{title} API"
109
+ end
110
+
111
+ def homepage
112
+ gem_config(:homepage) ||
113
+ "https://github.com/googleapis/googleapis"
114
+ end
115
+
116
+ def env_prefix
117
+ (gem_config(:env_prefix) || name.split("-").last).upcase
118
+ end
119
+
120
+ def iam_dependency?
121
+ @api.files.map(&:name).any? { |f| f.start_with? "google/iam/v1/" }
122
+ end
123
+
124
+ def library_documentation_url
125
+ gem_config(:library_documentation_url) || "https://googleapis.dev/ruby/#{name}/latest"
126
+ end
127
+
128
+ def product_documentation_url
129
+ gem_config :product_documentation_url
130
+ end
131
+
132
+ def api_id
133
+ gem_config :api_id
134
+ end
135
+
136
+ def free_tier?
137
+ gem_config(:free_tier) ? true : false
138
+ end
139
+
140
+ def yard_strict?
141
+ gem_config(:yard_strict) ? true : false
142
+ end
143
+
144
+ def entrypoint_require
145
+ packages.first.package_require
146
+ end
147
+
148
+ private
149
+
150
+ def gem_config key
151
+ return unless @api.configuration[:gem]
152
+
153
+ @api.configuration[:gem][key]
154
+ end
155
+
156
+ def blacklist_protos
157
+ blacklist = gem_config :blacklist
158
+
159
+ return default_blacklist_protos if blacklist.nil?
160
+ return default_blacklist_protos if blacklist[:protos].nil?
161
+
162
+ default_blacklist_protos[:protos]
163
+ end
164
+
165
+ def default_blacklist_protos
166
+ ["google/api/http.proto", "google/protobuf/descriptor.proto"]
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,73 @@
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
+
19
+ require "gapic/helpers/namespace_helper"
20
+
21
+ module Gapic
22
+ module Presenters
23
+ ##
24
+ # A presenter for proto messages.
25
+ #
26
+ class MessagePresenter
27
+ include Gapic::Helpers::NamespaceHelper
28
+
29
+ def initialize api, message
30
+ @api = api
31
+ @message = message
32
+ end
33
+
34
+ def name
35
+ @message.name
36
+ end
37
+
38
+ def doc_types
39
+ type_name_full
40
+ end
41
+
42
+ def doc_description
43
+ @message.docs_leading_comments
44
+ end
45
+
46
+ def default_value
47
+ "{}"
48
+ end
49
+
50
+ def type_name_full
51
+ message_ruby_type @message
52
+ end
53
+
54
+ def fields
55
+ @fields = @message.fields.map { |f| FieldPresenter.new @api, @message, f }
56
+ end
57
+
58
+ def nested_enums
59
+ @nested_enums ||= @message.nested_enums.map { |e| EnumPresenter.new e }
60
+ end
61
+
62
+ def nested_messages
63
+ @nested_messages ||= @message.nested_messages.map { |m| MessagePresenter.new @api, m }
64
+ end
65
+
66
+ protected
67
+
68
+ def message_ruby_type message
69
+ ruby_namespace @api, message.address.join(".")
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,298 @@
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
+ paged_request?(@method.input) && paged_response?(@method.output)
164
+ end
165
+
166
+ def paged_response_type
167
+ return nil unless paged_response? @method.output
168
+
169
+ repeated_field = @method.output.fields.find do |f|
170
+ f.label == Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED &&
171
+ f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
172
+ end
173
+ message_ruby_type repeated_field.message
174
+ end
175
+
176
+ ##
177
+ #
178
+ # @return [Array<String>] The segment key names.
179
+ #
180
+ def routing_params
181
+ segments = Gapic::PathTemplate.parse method_path
182
+ segments.select { |s| s.is_a? Gapic::PathTemplate::Segment }.map(&:name)
183
+ end
184
+
185
+ def routing_params?
186
+ routing_params.any?
187
+ end
188
+
189
+ def grpc_service_config
190
+ if @api.grpc_service_config&.service_method_level_configs&.key?(service.grpc_full_name) &&
191
+ @api.grpc_service_config.service_method_level_configs[service.grpc_full_name]&.key?(grpc_method_name)
192
+ @api.grpc_service_config.service_method_level_configs[service.grpc_full_name][grpc_method_name]
193
+ end
194
+ end
195
+
196
+ def grpc_method_name
197
+ @method.name
198
+ end
199
+
200
+ protected
201
+
202
+ def message_ruby_type message
203
+ ruby_namespace @api, message.address.join(".")
204
+ end
205
+
206
+ def doc_types_for arg
207
+ if arg.message?
208
+ "#{message_ruby_type arg.message} | Hash"
209
+ elsif arg.enum?
210
+ # TODO: handle when arg message is nil and enum is the type
211
+ message_ruby_type arg.enum
212
+ else
213
+ case arg.type
214
+ when 1, 2 then "Float"
215
+ when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "Integer"
216
+ when 9, 12 then "String"
217
+ when 8 then "Boolean"
218
+ else
219
+ "Object"
220
+ end
221
+ end
222
+ end
223
+
224
+ def doc_desc_for arg
225
+ return nil if arg.docs.leading_comments.empty?
226
+
227
+ arg.docs.leading_comments
228
+ end
229
+
230
+ def default_value_for arg
231
+ if arg.message?
232
+ "{}"
233
+ elsif arg.enum?
234
+ # TODO: select the first non-0 enum value
235
+ # ":ENUM"
236
+ arg.enum.values.first
237
+ else
238
+ case arg.type
239
+ when 1, 2 then "3.14"
240
+ when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "42"
241
+ when 9, 12 then "\"hello world\""
242
+ when 8 then "true"
243
+ else
244
+ "Object"
245
+ end
246
+ end
247
+ end
248
+
249
+ def method_path
250
+ return "" if @method.http.nil?
251
+
252
+ method = [
253
+ @method.http.get, @method.http.post, @method.http.put,
254
+ @method.http.patch, @method.http.delete
255
+ ].find { |x| !x.empty? }
256
+ return method unless method.nil?
257
+
258
+ return @method.http.custom.path unless @method.http.custom.nil?
259
+ end
260
+
261
+ def paged_request? request
262
+ page_token = request.fields.find do |f|
263
+ f.name == "page_token" && f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
264
+ end
265
+ return false if page_token.nil?
266
+
267
+ page_size_types = [
268
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32,
269
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64
270
+ ]
271
+ page_size = request.fields.find do |f|
272
+ f.name == "page_size" && page_size_types.include?(f.type)
273
+ end
274
+ return false if page_size.nil?
275
+
276
+ true
277
+ end
278
+
279
+ def paged_response? response
280
+ next_page_token = response.fields.find do |f|
281
+ f.name == "next_page_token" && f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
282
+ end
283
+ return false if next_page_token.nil?
284
+
285
+ repeated_field = response.fields.find do |f|
286
+ f.label == Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED &&
287
+ f.type == Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
288
+ end
289
+ return false if repeated_field.nil?
290
+
291
+ # We want to make sure the first repeated field is also has the lowest field number,
292
+ # but the google-protobuf gem sorts fields by number, so we lose the original order.
293
+
294
+ true
295
+ end
296
+ end
297
+ end
298
+ end