gapic-generator 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/lib/gapic/generator/version.rb +1 -1
  4. data/lib/gapic/generators/default_generator.rb +18 -5
  5. data/lib/gapic/generators/default_generator_parameters.rb +8 -4
  6. data/lib/gapic/presenters.rb +3 -0
  7. data/lib/gapic/presenters/field_presenter.rb +44 -0
  8. data/lib/gapic/presenters/gem_presenter.rb +47 -10
  9. data/lib/gapic/presenters/method_presenter.rb +36 -16
  10. data/lib/gapic/presenters/method_rest_presenter.rb +194 -0
  11. data/lib/gapic/presenters/package_presenter.rb +18 -0
  12. data/lib/gapic/presenters/service_presenter.rb +42 -4
  13. data/lib/gapic/presenters/service_rest_presenter.rb +139 -0
  14. data/lib/gapic/presenters/snippet_presenter.rb +103 -0
  15. data/lib/gapic/runner.rb +2 -1
  16. data/lib/gapic/schema/api.rb +58 -16
  17. data/lib/gapic/schema/request_param_parser.rb +46 -12
  18. data/lib/google/protobuf/any.pb.rb +1 -1
  19. data/lib/google/protobuf/compiler/plugin.pb.rb +9 -6
  20. data/lib/google/protobuf/descriptor.pb.rb +2 -2
  21. data/lib/google/protobuf/empty.pb.rb +1 -1
  22. data/templates/default/gem/readme.erb +2 -2
  23. data/templates/default/lib/_package.erb +11 -1
  24. data/templates/default/lib/_service.erb +31 -1
  25. data/templates/default/lib/rest/_rest.erb +11 -0
  26. data/templates/default/service/rest.erb +6 -0
  27. data/templates/default/service/rest/client.erb +6 -0
  28. data/templates/default/service/rest/client/_client.erb +115 -0
  29. data/templates/default/service/rest/client/_config.erb +74 -0
  30. data/templates/default/service/rest/client/_requires.erb +1 -0
  31. data/templates/default/service/rest/client/method/_def.erb +18 -0
  32. data/templates/default/service/rest/client/method/def/_options_defaults.erb +15 -0
  33. data/templates/default/service/rest/client/method/def/_rescue.erb +3 -0
  34. data/templates/default/service/rest/client/method/def/_response_normal.erb +17 -0
  35. data/templates/default/service/rest/client/method/docs/_error.erb +2 -0
  36. data/templates/default/service/rest/client/method/docs/_request.erb +27 -0
  37. data/templates/default/service/rest/client/method/docs/_result.erb +6 -0
  38. data/templates/default/service/rest/grpc_transcoding.erb +6 -0
  39. data/templates/default/service/rest/grpc_transcoding/_grpc_transcoding.erb +9 -0
  40. data/templates/default/service/rest/grpc_transcoding/method/_def.erb +21 -0
  41. data/templates/default/service/rest/grpc_transcoding/method/def/_query_string_param.erb +8 -0
  42. data/templates/default/service/rest/test/client.erb +18 -0
  43. data/templates/default/service/rest/test/method/_assert_response.erb +2 -0
  44. data/templates/default/service/rest/test/method/_configure.erb +19 -0
  45. data/templates/default/service/rest/test/method/_normal.erb +71 -0
  46. data/templates/default/service/rest/test/method/_setup.erb +38 -0
  47. data/templates/default/snippets/gemfile.erb +17 -0
  48. data/templates/default/snippets/snippet/_structure.erb +71 -0
  49. data/templates/default/snippets/standalone.erb +6 -0
  50. metadata +31 -3
@@ -54,7 +54,10 @@ module Gapic
54
54
  namespace.split("::").last
55
55
  end
56
56
 
57
+ ##
57
58
  # Services whose clients should be generated in this package namespace.
59
+ # @return [Enumerable<Gapic::Presenters::ServicePresenter>]
60
+ #
58
61
  def services
59
62
  @services ||= begin
60
63
  files = @api.generate_files.select { |f| f.package == @package }
@@ -117,6 +120,21 @@ module Gapic
117
120
  services: services.map { |s| [s.grpc_service_name, s.drift_manifest] }.to_h
118
121
  }
119
122
  end
123
+
124
+ ##
125
+ # How comments in the generated libraries refer to the GRPC client
126
+ # if no REST code is generated, this should just be "client",
127
+ # if REST code is generated, this should be disambiguated into the "GRPC client"
128
+ #
129
+ # Since we are using first service for an indication of whether package generates
130
+ # REST code, it's OK to defer this to the first service as well.
131
+ # For packages with no services the value of this does not really matter as
132
+ # no client generation docs will be generated.
133
+ #
134
+ # @return [String]
135
+ def grpc_client_designation
136
+ services.first&.grpc_client_designation || ""
137
+ end
120
138
  end
121
139
  end
122
140
  end
@@ -27,11 +27,15 @@ module Gapic
27
27
  include Gapic::Helpers::FilepathHelper
28
28
  include Gapic::Helpers::NamespaceHelper
29
29
 
30
+ # @return [Gapic::Presenters::ServiceRestPresenter]
31
+ attr_reader :rest
32
+
30
33
  def initialize gem_presenter, api, service, parent_service: nil
31
34
  @gem_presenter = gem_presenter
32
35
  @api = api
33
36
  @service = service
34
37
  @parent_service = parent_service
38
+ @rest = ServiceRestPresenter.new self, api
35
39
  end
36
40
 
37
41
  def gem
@@ -46,10 +50,11 @@ module Gapic
46
50
  PackagePresenter.new @gem_presenter, @api, @service.parent.package
47
51
  end
48
52
 
53
+ ##
54
+ # @return [Enumerable<Gapic::Presenters::MethodPresenter>]
55
+ #
49
56
  def methods
50
- @methods ||= begin
51
- @service.methods.map { |m| MethodPresenter.new self, @api, m }
52
- end
57
+ @methods ||= @service.methods.map { |m| MethodPresenter.new self, @api, m }
53
58
  end
54
59
 
55
60
  def address
@@ -271,6 +276,29 @@ module Gapic
271
276
  ruby_file_path @api, "#{service_name_full}::#{paths_name}"
272
277
  end
273
278
 
279
+ def generate_rest_clients?
280
+ @api.generate_rest_clients?
281
+ end
282
+
283
+ def generate_grpc_clients?
284
+ @api.generate_grpc_clients?
285
+ end
286
+
287
+ ##
288
+ # @return [Boolean] whether this service contains any methods with REST bindings
289
+ #
290
+ def methods_rest_bindings?
291
+ methods_rest_bindings.any?
292
+ end
293
+
294
+ ##
295
+ # @return [Enumerable<Gapic::Presenters::MethodPresenter>]
296
+ # List of mods for which REST bindings are present and REST methods can be generated
297
+ #
298
+ def methods_rest_bindings
299
+ methods.select { |method| method.rest.path? && method.rest.verb? }
300
+ end
301
+
274
302
  def test_client_file_path
275
303
  service_file_path.sub ".rb", "_test.rb"
276
304
  end
@@ -361,12 +389,22 @@ module Gapic
361
389
  # their names are returned together in an array.
362
390
  # For Ruby currently we have 1:1 proto to code
363
391
  # correspondence for methods, so our generation is easier
364
- methods: methods.map { |m| [m.grpc_method_name, [m.name]] }.to_h
392
+ rpcs: methods.map { |m| [m.grpc_method_name, m.drift_manifest] }.to_h
365
393
  }
366
394
  }
367
395
  }
368
396
  end
369
397
 
398
+ ##
399
+ # How comments in the generated libraries refer to the GRPC client
400
+ # if no REST code is generated, this should just be "client",
401
+ # if REST code is generated, this should be disambiguated into the "GRPC client"
402
+ #
403
+ # @return [String]
404
+ def grpc_client_designation
405
+ generate_rest_clients? ? "GRPC client" : "client"
406
+ end
407
+
370
408
  private
371
409
 
372
410
  def default_config key
@@ -0,0 +1,139 @@
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 "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 service (REST submethods)
25
+ #
26
+ class ServiceRestPresenter
27
+ include Gapic::Helpers::FilepathHelper
28
+ include Gapic::Helpers::NamespaceHelper
29
+
30
+ ##
31
+ # @param main_service [Gapic::Presenters::ServicePresenter]
32
+ # @param api [Gapic::Schema::Api]
33
+ #
34
+ def initialize main_service, api
35
+ @main_service = main_service
36
+ @api = api
37
+ end
38
+
39
+ ##
40
+ # @return [String]
41
+ #
42
+ def service_name_full
43
+ fix_namespace api, "#{main_service.service_name_full}::Rest"
44
+ end
45
+
46
+ ##
47
+ # @return [String]
48
+ #
49
+ def client_name
50
+ main_service.client_name
51
+ end
52
+
53
+ ##
54
+ # @return [String]
55
+ #
56
+ def client_name_full
57
+ fix_namespace api, "#{service_name_full}::#{client_name}"
58
+ end
59
+
60
+ ##
61
+ # @return [String]
62
+ #
63
+ def client_require
64
+ ruby_file_path api, client_name_full
65
+ end
66
+
67
+ ##
68
+ # @return [String]
69
+ #
70
+ def client_file_path
71
+ "#{client_require}.rb"
72
+ end
73
+
74
+ ##
75
+ # @return [String]
76
+ #
77
+ def create_client_call
78
+ "#{client_name_full}.new"
79
+ end
80
+
81
+ ##
82
+ # @return [String]
83
+ #
84
+ def service_rest_require
85
+ ruby_file_path api, service_name_full
86
+ end
87
+
88
+ ##
89
+ # @return [String]
90
+ #
91
+ def service_rest_file_path
92
+ "#{service_rest_require}.rb"
93
+ end
94
+
95
+ ##
96
+ # @return [String]
97
+ #
98
+ def transcoding_helper_name
99
+ "GrpcTranscoding"
100
+ end
101
+
102
+ ##
103
+ # @return [String]
104
+ #
105
+ def transcoding_helper_name_full
106
+ fix_namespace api, "#{service_name_full}::#{transcoding_helper_name}"
107
+ end
108
+
109
+ ##
110
+ # @return [String]
111
+ #
112
+ def transcoding_helper_require
113
+ ruby_file_path api, transcoding_helper_name_full
114
+ end
115
+
116
+ ##
117
+ # @return [String]
118
+ #
119
+ def transcoding_helper_file_path
120
+ "#{transcoding_helper_require}.rb"
121
+ end
122
+
123
+ ##
124
+ # @return [String]
125
+ #
126
+ def test_client_file_path
127
+ main_service.service_file_path.sub ".rb", "_test.rb"
128
+ end
129
+
130
+
131
+ private
132
+
133
+ # @return [Gapic::Presenters::ServicePresenter]
134
+ attr_reader :main_service
135
+ # @return [Gapic::Schema::Api]
136
+ attr_reader :api
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,103 @@
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 "active_support/inflector"
18
+
19
+ module Gapic
20
+ module Presenters
21
+ ##
22
+ # A presenter for snippets.
23
+ #
24
+ class SnippetPresenter
25
+ def initialize method_presenter, api
26
+ @method_presenter = method_presenter
27
+ @api = api
28
+ end
29
+
30
+ def client_streaming?
31
+ @method_presenter.client_streaming?
32
+ end
33
+
34
+ def bidi_streaming?
35
+ @method_presenter.client_streaming? && @method_presenter.server_streaming?
36
+ end
37
+
38
+ def response_kind
39
+ if @method_presenter.server_streaming?
40
+ :streaming
41
+ elsif @method_presenter.paged?
42
+ :paged
43
+ elsif @method_presenter.lro?
44
+ :lro
45
+ else
46
+ :simple
47
+ end
48
+ end
49
+
50
+ def snippet_file_path
51
+ "#{@method_presenter.service.service_require.split('/').last}/#{@method_presenter.name}.rb"
52
+ end
53
+
54
+ def require_path
55
+ @method_presenter.service.service_require
56
+ end
57
+
58
+ def client_type
59
+ @method_presenter.service.client_name_full.sub(/^::/, "")
60
+ end
61
+
62
+ def request_type
63
+ @method_presenter.request_type.sub(/^::/, "")
64
+ end
65
+
66
+ def return_type
67
+ base_type = @method_presenter.return_type.sub(/^::/, "")
68
+ @method_presenter.server_streaming? ? "Enumerable<#{base_type}>" : base_type
69
+ end
70
+
71
+ def paged_response_type
72
+ @method_presenter.paged_response_type
73
+ end
74
+
75
+ def base_response_type
76
+ @method_presenter.return_type
77
+ end
78
+
79
+ # TODO: Determine type of LRO response
80
+
81
+ def method_name
82
+ @method_presenter.name
83
+ end
84
+
85
+ def region_tag
86
+ gem_presenter = @method_presenter.service.gem
87
+ api_id = gem_presenter.api_shortname || gem_presenter.api_id&.split(".")&.first
88
+ names = gem_presenter.name.split "-"
89
+ final_name = names.pop
90
+ if final_name =~ /^v\d/
91
+ api_version = final_name
92
+ api_id ||= names.last
93
+ else
94
+ api_id ||= final_name
95
+ api_version = "v0"
96
+ end
97
+ service_name = @method_presenter.service.module_name
98
+ method_name = @method_presenter.method.name
99
+ "#{api_id}_#{api_version}_generated_#{service_name}_#{method_name}_sync"
100
+ end
101
+ end
102
+ end
103
+ end
data/lib/gapic/runner.rb CHANGED
@@ -65,7 +65,8 @@ module Gapic
65
65
 
66
66
  # Create and write the response
67
67
  response = Google::Protobuf::Compiler::CodeGeneratorResponse.new file: output_files
68
- response.supported_features = Google::Protobuf::Compiler::CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL
68
+ feature_set = Google::Protobuf::Compiler::CodeGeneratorResponse::Feature::FEATURE_PROTO3_OPTIONAL.to_i
69
+ response.supported_features = feature_set
69
70
  response
70
71
  end
71
72
 
@@ -89,6 +89,10 @@ module Gapic
89
89
  matching_files.first
90
90
  end
91
91
 
92
+ def overrides_of key
93
+ configuration&.fetch(:overrides, nil)&.fetch(key, nil) || {}
94
+ end
95
+
92
96
  def fix_file_path str
93
97
  str = String str
94
98
  return str if configuration[:overrides].nil?
@@ -144,11 +148,9 @@ module Gapic
144
148
  # @return [Array<Hash>]
145
149
  # An array of the sample file hashes.
146
150
  def samples
147
- @samples ||= begin
148
- protoc_options["samples"].to_s.split(";").flat_map do |sample_path|
149
- YAML.load_file sample_path
150
- end.compact
151
- end
151
+ @samples ||= protoc_options["samples"].to_s.split(";").flat_map do |sample_path|
152
+ YAML.load_file sample_path
153
+ end.compact
152
154
  end
153
155
 
154
156
  # Structured representation of the standalone samples configuration files.
@@ -174,10 +176,10 @@ module Gapic
174
176
  # An array of the standalone sample configuration hashes.
175
177
  def standalone_test_samples
176
178
  @standalone_test_samples ||= begin
177
- samples.select { |sample| sample["type"] == "test/samples" }
178
- .select { |sample| sample["schema_version"] == "1" || sample["schema_version"] == 1 }
179
- .map { |sample| sample["samples"] }
180
- .flatten.compact
179
+ test_samples = samples.select { |sample| sample["type"] == "test/samples" }
180
+ test_samples.select { |sample| sample["schema_version"] == "1" || sample["schema_version"] == 1 }
181
+ .map { |sample| sample["samples"] }
182
+ .flatten.compact
181
183
  end
182
184
  end
183
185
 
@@ -231,6 +233,29 @@ module Gapic
231
233
  configuration[:generate_path_helpers_output] ||= false
232
234
  end
233
235
 
236
+ # Whether to generate REST clients
237
+ def generate_rest_clients?
238
+ return false if configuration[:transports].nil?
239
+ configuration[:transports].include? "rest"
240
+ end
241
+
242
+ # Whether to generate GRPC clients
243
+ def generate_grpc_clients?
244
+ return true if configuration[:transports].nil?
245
+ configuration[:transports].include? "grpc"
246
+ end
247
+
248
+ # Whether to generate standalone snippets
249
+ def generate_standalone_snippets?
250
+ configuration[:generate_standalone_snippets] ||= false
251
+ end
252
+
253
+ # Whether to generate gapic metadata (drift manifest) file
254
+ # @return [Boolean]
255
+ def generate_metadata
256
+ configuration[:generate_metadata] ||= false
257
+ end
258
+
234
259
  # Whether the override_proto_namespaces parameter was given in the configuration
235
260
  def override_proto_namespaces_defined?
236
261
  configuration.key? :override_proto_namespaces
@@ -260,9 +285,7 @@ module Gapic
260
285
 
261
286
  # Parsed grpc service config
262
287
  def grpc_service_config
263
- @grpc_service_config ||= begin
264
- Gapic::GrpcServiceConfig::Parser.parse grpc_service_config_raw
265
- end
288
+ @grpc_service_config ||= Gapic::GrpcServiceConfig::Parser.parse grpc_service_config_raw
266
289
  end
267
290
 
268
291
  # Get a resource given its type string
@@ -272,10 +295,8 @@ module Gapic
272
295
 
273
296
  # Given a service, find all common services that use it as a delegate.
274
297
  def common_services_for delegate
275
- @delegate_to_common ||= begin
276
- (configuration[:common_services] || {}).each_with_object({}) do |(c, d), mapping|
277
- (mapping[d] ||= []) << c
278
- end
298
+ @delegate_to_common ||= (configuration[:common_services] || {}).each_with_object({}) do |(c, d), mapping|
299
+ (mapping[d] ||= []) << c
279
300
  end
280
301
  all_services = services
281
302
  @delegate_to_common.fetch(delegate.address.join("."), []).map do |addr|
@@ -292,6 +313,27 @@ module Gapic
292
313
  services.find { |s| s.address == addr }
293
314
  end
294
315
 
316
+ ##
317
+ # Whether configuration has an override for the wrapper gem name
318
+ # @return [Boolean]
319
+ def wrapper_gem_name_override?
320
+ configuration.key?(:overrides) &&
321
+ configuration[:overrides].key?(:wrapper_gem_name)
322
+ end
323
+
324
+ ##
325
+ # An override for the wrapper gem name in the configuration
326
+ # @return [String, Nil]
327
+ def wrapper_gem_name_override
328
+ return nil unless wrapper_gem_name_override?
329
+ return nil if configuration[:overrides][:wrapper_gem_name].nil?
330
+
331
+ wrapper_name_config = configuration[:overrides][:wrapper_gem_name].strip
332
+ return nil if wrapper_name_config.empty?
333
+
334
+ wrapper_name_config
335
+ end
336
+
295
337
  private
296
338
 
297
339
  # Perform a variety of sanity checks on the data, and prints errors to