gapic-generator 0.3.3 → 0.6.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/lib/gapic/formatting_utils.rb +7 -7
  4. data/lib/gapic/generator/version.rb +1 -1
  5. data/lib/gapic/generators/default_generator.rb +16 -14
  6. data/lib/gapic/helpers/filepath_helper.rb +1 -0
  7. data/lib/gapic/helpers/namespace_helper.rb +8 -1
  8. data/lib/gapic/path_template/segment.rb +7 -0
  9. data/lib/gapic/presenters/field_presenter.rb +9 -9
  10. data/lib/gapic/presenters/file_presenter.rb +1 -1
  11. data/lib/gapic/presenters/gem_presenter.rb +28 -2
  12. data/lib/gapic/presenters/method_presenter.rb +23 -17
  13. data/lib/gapic/presenters/package_presenter.rb +11 -3
  14. data/lib/gapic/presenters/resource_presenter.rb +55 -35
  15. data/lib/gapic/presenters/service_presenter.rb +66 -23
  16. data/lib/gapic/ruby_info.rb +93 -0
  17. data/lib/gapic/schema/api.rb +63 -1
  18. data/templates/default/gem/gemfile.erb +3 -0
  19. data/templates/default/gem/gemspec.erb +7 -6
  20. data/templates/default/gem/rakefile.erb +1 -0
  21. data/templates/default/gem/test_helper.erb +8 -0
  22. data/templates/default/layouts/_ruby.erb +5 -4
  23. data/templates/default/lib/_service.erb +2 -0
  24. data/templates/default/proto_docs/_message.erb +2 -2
  25. data/templates/default/service/client.erb +1 -1
  26. data/templates/default/service/client/_client.erb +17 -4
  27. data/templates/default/service/client/_config.erb +33 -29
  28. data/templates/default/service/client/_credentials.erb +1 -1
  29. data/templates/default/service/client/_operations.erb +3 -1
  30. data/templates/default/service/client/method/def/_options_defaults.erb +2 -2
  31. data/templates/default/service/client/method/def/_request_normal.erb +2 -2
  32. data/templates/default/service/client/method/def/_request_streaming.erb +3 -3
  33. data/templates/default/service/client/method/def/_response_normal.erb +1 -1
  34. data/templates/default/service/client/method/def/_response_paged.erb +2 -2
  35. data/templates/default/service/client/method/docs/_error.erb +1 -1
  36. data/templates/default/service/client/method/docs/_request_normal.erb +2 -2
  37. data/templates/default/service/client/method/docs/_request_streaming.erb +2 -2
  38. data/templates/default/service/client/method/docs/_response.erb +1 -1
  39. data/templates/default/service/client/resource/_def.erb +1 -1
  40. data/templates/default/service/client/resource/_multi.erb +4 -7
  41. data/templates/default/service/client/resource/_single.erb +2 -3
  42. data/templates/default/service/credentials.erb +1 -1
  43. data/templates/default/service/operations.erb +1 -1
  44. data/templates/default/service/paths.erb +1 -1
  45. data/templates/default/service/test/_resource.erb +16 -0
  46. data/templates/default/service/test/client.erb +17 -4
  47. data/templates/default/service/test/client_operations.erb +3 -4
  48. data/templates/default/service/test/client_paths.erb +17 -0
  49. data/templates/default/service/test/method/_configure.erb +19 -0
  50. metadata +8 -3
@@ -27,14 +27,15 @@ module Gapic
27
27
  include Gapic::Helpers::FilepathHelper
28
28
  include Gapic::Helpers::NamespaceHelper
29
29
 
30
- def initialize api, service, parent_service: nil
30
+ def initialize gem_presenter, api, service, parent_service: nil
31
+ @gem_presenter = gem_presenter
31
32
  @api = api
32
33
  @service = service
33
34
  @parent_service = parent_service
34
35
  end
35
36
 
36
37
  def gem
37
- GemPresenter.new @api
38
+ @gem_presenter
38
39
  end
39
40
 
40
41
  def file
@@ -42,12 +43,12 @@ module Gapic
42
43
  end
43
44
 
44
45
  def package
45
- PackagePresenter.new @api, @service.parent.package
46
+ PackagePresenter.new @gem_presenter, @api, @service.parent.package
46
47
  end
47
48
 
48
49
  def methods
49
50
  @methods ||= begin
50
- @service.methods.map { |m| MethodPresenter.new @api, m }
51
+ @service.methods.map { |m| MethodPresenter.new self, @api, m }
51
52
  end
52
53
  end
53
54
 
@@ -55,8 +56,26 @@ module Gapic
55
56
  @service.address
56
57
  end
57
58
 
59
+ # Returns a presenter for this service's delegate (if it is a common service)
60
+ # otherwise returns `nil`.
61
+ def common_service_delegate
62
+ unless defined? @common_service_delegate
63
+ delegate = @api.delegate_service_for @service
64
+ @common_service_delegate = delegate ? ServicePresenter.new(@gem_presenter, @api, delegate) : nil
65
+ end
66
+ @common_service_delegate
67
+ end
68
+
69
+ # The namespace of the client. Normally this is the version module. This
70
+ # may be different from the proto namespace for a common service.
58
71
  def namespace
59
- return @service.ruby_package if @service.ruby_package.present?
72
+ # If this service is a common service, its client should go into its
73
+ # delegate's namespace rather than its own. For example, KMS includes
74
+ # the common IAMPolicy service, but that service's client should go
75
+ # into the KMS namespace.
76
+ return common_service_delegate.namespace if common_service_delegate
77
+
78
+ return ensure_absolute_namespace @service.ruby_package if @service.ruby_package.present?
60
79
 
61
80
  namespace = ruby_namespace_for_address @service.address[0...-1]
62
81
  fix_namespace @api, namespace
@@ -71,15 +90,25 @@ module Gapic
71
90
  end
72
91
 
73
92
  def name
74
- @service.name
93
+ @api.fix_service_name @service.name
94
+ end
95
+
96
+ # The namespace of the protos. This may be different from the client
97
+ # namespace for a common service.
98
+ def proto_namespace
99
+ return ensure_absolute_namespace @service.ruby_package if @service.ruby_package.present?
100
+
101
+ namespace = ruby_namespace_for_address @service.address[0...-1]
102
+ @api.override_proto_namespaces? ? fix_namespace(@api, namespace) : namespace
75
103
  end
76
104
 
77
105
  def proto_service_name_full
78
- fix_namespace @api, "#{namespace}::#{name}"
106
+ name_full = "#{proto_namespace}::#{@service.name}"
107
+ @api.override_proto_namespaces? ? fix_namespace(@api, name_full) : name_full
79
108
  end
80
109
 
81
110
  def module_name
82
- proto_service_name_full.split("::").last
111
+ service_name_full.split("::").last
83
112
  end
84
113
 
85
114
  def proto_service_file_path
@@ -110,6 +139,10 @@ module Gapic
110
139
  "#{proto_service_name_full}::Stub"
111
140
  end
112
141
 
142
+ def service_name_full
143
+ fix_namespace @api, "#{namespace}::#{name}"
144
+ end
145
+
113
146
  def service_file_path
114
147
  service_require + ".rb"
115
148
  end
@@ -123,7 +156,7 @@ module Gapic
123
156
  end
124
157
 
125
158
  def service_require
126
- ruby_file_path @api, proto_service_name_full
159
+ ruby_file_path @api, service_name_full
127
160
  end
128
161
 
129
162
  def client_name
@@ -131,7 +164,7 @@ module Gapic
131
164
  end
132
165
 
133
166
  def client_name_full
134
- fix_namespace @api, "#{proto_service_name_full}::#{client_name}"
167
+ fix_namespace @api, "#{service_name_full}::#{client_name}"
135
168
  end
136
169
 
137
170
  def create_client_call
@@ -155,16 +188,22 @@ module Gapic
155
188
  end
156
189
 
157
190
  def client_endpoint
158
- return @parent_service.client_endpoint if @parent_service
159
- @service.host || default_config(:default_host) || "localhost"
191
+ return nil if generic_endpoint?
192
+ @parent_service&.client_endpoint ||
193
+ common_service_delegate&.client_endpoint ||
194
+ @service.host ||
195
+ default_config(:default_host) ||
196
+ "localhost"
160
197
  end
161
198
 
162
- def client_scopes
163
- @service.scopes || default_config(:oauth_scopes)
199
+ def generic_endpoint?
200
+ gem.generic_endpoint?
164
201
  end
165
202
 
166
- def client_proto_name
167
- @service.address.join "."
203
+ def client_scopes
204
+ common_service_delegate&.client_scopes ||
205
+ @service.scopes ||
206
+ default_config(:oauth_scopes)
168
207
  end
169
208
 
170
209
  def credentials_name
@@ -172,7 +211,7 @@ module Gapic
172
211
  end
173
212
 
174
213
  def credentials_name_full
175
- fix_namespace @api, "#{proto_service_name_full}::#{credentials_name}"
214
+ fix_namespace @api, "#{service_name_full}::#{credentials_name}"
176
215
  end
177
216
 
178
217
  def credentials_class_xref
@@ -200,7 +239,7 @@ module Gapic
200
239
  end
201
240
 
202
241
  def helpers_require
203
- ruby_file_path @api, "#{proto_service_name_full}::Helpers"
242
+ ruby_file_path @api, "#{service_name_full}::Helpers"
204
243
  end
205
244
 
206
245
  def references
@@ -216,7 +255,7 @@ module Gapic
216
255
  end
217
256
 
218
257
  def paths_name_full
219
- fix_namespace @api, "#{proto_service_name_full}::#{paths_name}"
258
+ fix_namespace @api, "#{service_name_full}::#{paths_name}"
220
259
  end
221
260
 
222
261
  def paths_file_path
@@ -228,13 +267,17 @@ module Gapic
228
267
  end
229
268
 
230
269
  def paths_require
231
- ruby_file_path @api, "#{proto_service_name_full}::#{paths_name}"
270
+ ruby_file_path @api, "#{service_name_full}::#{paths_name}"
232
271
  end
233
272
 
234
273
  def test_client_file_path
235
274
  service_file_path.sub ".rb", "_test.rb"
236
275
  end
237
276
 
277
+ def test_paths_file_path
278
+ service_file_path.sub ".rb", "_paths_test.rb"
279
+ end
280
+
238
281
  def test_client_operations_file_path
239
282
  service_file_path.sub ".rb", "_operations_test.rb"
240
283
  end
@@ -260,7 +303,7 @@ module Gapic
260
303
  end
261
304
 
262
305
  def operations_name_full
263
- fix_namespace @api, "#{proto_service_name_full}::#{operations_name}"
306
+ fix_namespace @api, "#{service_name_full}::#{operations_name}"
264
307
  end
265
308
 
266
309
  def operations_file_path
@@ -272,12 +315,12 @@ module Gapic
272
315
  end
273
316
 
274
317
  def operations_require
275
- ruby_file_path @api, "#{proto_service_name_full}::#{operations_name}"
318
+ ruby_file_path @api, "#{service_name_full}::#{operations_name}"
276
319
  end
277
320
 
278
321
  def lro_service
279
322
  lro = @service.parent.parent.files.find { |file| file.name == "google/longrunning/operations.proto" }
280
- return ServicePresenter.new @api, lro.services.first, parent_service: self unless lro.nil?
323
+ return ServicePresenter.new @gem_presenter, @api, lro.services.first, parent_service: self unless lro.nil?
281
324
  end
282
325
 
283
326
  def config_channel_args
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2020 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
+ ##
19
+ # Various Ruby language information useful for generators.
20
+ #
21
+ module RubyInfo
22
+ class << self
23
+ ##
24
+ # A sorted list of Ruby's keywords.
25
+ #
26
+ # @see https://docs.ruby-lang.org/en/2.7.0/keywords_rdoc.html
27
+ #
28
+ # @return [Array<String>]
29
+ #
30
+ def keywords
31
+ @keywords ||= [
32
+ "__ENCODING__",
33
+ "__LINE__",
34
+ "__FILE__",
35
+ "BEGIN",
36
+ "END",
37
+ "alias",
38
+ "and",
39
+ "begin",
40
+ "break",
41
+ "case",
42
+ "class",
43
+ "def",
44
+ "defined?",
45
+ "do",
46
+ "else",
47
+ "elsif",
48
+ "end",
49
+ "ensure",
50
+ "false",
51
+ "for",
52
+ "if",
53
+ "in",
54
+ "module",
55
+ "next",
56
+ "nil",
57
+ "not",
58
+ "or",
59
+ "redo",
60
+ "rescue",
61
+ "retry",
62
+ "return",
63
+ "self",
64
+ "super",
65
+ "then",
66
+ "true",
67
+ "undef",
68
+ "unless",
69
+ "until",
70
+ "when",
71
+ "while",
72
+ "yield"
73
+ ].freeze
74
+ end
75
+
76
+ ##
77
+ # A sorted list of method names that generated code should avoid.
78
+ # This includes methods of the Object class (including BasicObject and
79
+ # Kernel), Ruby keywords, and a few special names including "initialize"
80
+ # and "configure".
81
+ #
82
+ # @return [Array<String>]
83
+ #
84
+ def excluded_method_names
85
+ @excluded_method_names ||= begin
86
+ object_methods = (Object.instance_methods + Object.private_instance_methods).map(&:to_s)
87
+ other_methods = ["configure", "initialize"]
88
+ (object_methods + other_methods + keywords).sort.freeze
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -91,6 +91,13 @@ module Gapic
91
91
  configuration[:overrides][:namespace].fetch str, str
92
92
  end
93
93
 
94
+ def fix_service_name str
95
+ str = String str
96
+ return str if configuration[:overrides].nil?
97
+ return str if configuration[:overrides][:service].nil?
98
+ configuration[:overrides][:service].fetch str, str
99
+ end
100
+
94
101
  def generate_files
95
102
  @files.select(&:generate?)
96
103
  end
@@ -202,7 +209,7 @@ module Gapic
202
209
  config = config_file ? YAML.load_file(config_file) : {}
203
210
  protoc_options.each do |k, v|
204
211
  next if k == "configuration"
205
- branch = key_to_str(k).split(".").reverse.inject(v) { |m, s| { str_to_key(s) => m } }
212
+ branch = parse_key(key_to_str(k)).reverse.inject(v) { |m, s| { str_to_key(s) => m } }
206
213
  config = deep_merge config, branch
207
214
  end
208
215
  config
@@ -225,6 +232,21 @@ module Gapic
225
232
  configuration[:generate_path_helpers_output] ||= false
226
233
  end
227
234
 
235
+ # Whether the override_proto_namespaces parameter was given in the configuration
236
+ def override_proto_namespaces_defined?
237
+ configuration.key? :override_proto_namespaces
238
+ end
239
+
240
+ # Sets the override_proto_namespaces parameter in the configuration
241
+ def override_proto_namespaces= value
242
+ configuration[:override_proto_namespaces] = value
243
+ end
244
+
245
+ # Whether namespace overrides apply to proto/grpc class references
246
+ def override_proto_namespaces?
247
+ configuration[:override_proto_namespaces] ||= false
248
+ end
249
+
228
250
  # Raw parsed json of the combined grpc service config files if provided
229
251
  # or an empty hash if no config was provided
230
252
  def grpc_service_config_raw
@@ -249,6 +271,28 @@ module Gapic
249
271
  @resource_types[resource_type]
250
272
  end
251
273
 
274
+ # Given a service, find all common services that use it as a delegate.
275
+ def common_services_for delegate
276
+ @delegate_to_common ||= begin
277
+ (configuration[:common_services] || {}).each_with_object({}) do |(c, d), mapping|
278
+ (mapping[d] ||= []) << c
279
+ end
280
+ end
281
+ all_services = services
282
+ @delegate_to_common.fetch(delegate.address.join("."), []).map do |addr|
283
+ addr = addr.split "."
284
+ all_services.find { |s| s.address == addr }
285
+ end.compact.uniq
286
+ end
287
+
288
+ # Given a common service, return its delegate.
289
+ def delegate_service_for common
290
+ addr = (configuration[:common_services] || {})[common.address.join "."]
291
+ return nil unless addr
292
+ addr = addr.split "."
293
+ services.find { |s| s.address == addr }
294
+ end
295
+
252
296
  private
253
297
 
254
298
  # Does a pre-analysis of all resources defined in the job. This has
@@ -291,6 +335,8 @@ module Gapic
291
335
  end
292
336
  end
293
337
 
338
+ # Parse a comma-delimited list of equals-delimited lists of strings, while
339
+ # mapping backslash-escaped commas and equal signs to literal characters.
294
340
  def parse_parameter str
295
341
  str.scan(/\\.|,|=|[^\\,=]+/)
296
342
  .each_with_object([[String.new]]) do |tok, arr|
@@ -307,6 +353,22 @@ module Gapic
307
353
  end
308
354
  end
309
355
 
356
+ # split the string on periods, but map backslash-escaped periods to
357
+ # literal periods.
358
+ def parse_key str
359
+ str.scan(/\.|\\.|[^\.\\]+/)
360
+ .each_with_object([String.new]) do |tok, arr|
361
+ if tok == "."
362
+ arr.append String.new
363
+ elsif tok.start_with? "\\"
364
+ arr.last << tok[1]
365
+ else
366
+ arr.last << tok
367
+ end
368
+ arr
369
+ end
370
+ end
371
+
310
372
  def str_to_key str
311
373
  str = str.to_s
312
374
  str.start_with?(":") ? str[1..-1].to_sym : str
@@ -2,3 +2,6 @@
2
2
  source "https://rubygems.org"
3
3
 
4
4
  gemspec
5
+
6
+ # google-protobuf 3.12.0 requires Ruby 2.5 or later, so pin to 3.11 on older Rubies
7
+ gem "google-protobuf", (RUBY_VERSION < "2.5" ? "~> 3.11.4" : "~> 3.12")
@@ -12,24 +12,25 @@ Gem::Specification.new do |gem|
12
12
  gem.description = <%= gem.description.inspect %>
13
13
  gem.summary = <%= gem.summary.inspect %>
14
14
  gem.homepage = <%= gem.homepage.inspect %>
15
- gem.license = "MIT"
15
+ gem.license = <%= gem.license_name.inspect %>
16
16
 
17
17
  gem.platform = Gem::Platform::RUBY
18
18
 
19
19
  gem.files = `git ls-files -- lib/*`.split("\n") +
20
20
  `git ls-files -- proto_docs/*`.split("\n") +
21
- ["README.md", "LICENSE.md", ".yardopts"]
21
+ <%= gem.extra_files.inspect %>
22
22
  gem.require_paths = ["lib"]
23
23
 
24
24
  gem.required_ruby_version = ">= 2.4"
25
25
 
26
- gem.add_dependency "gapic-common", "~> 0.2"
27
- <%- if gem.iam_dependency? -%>
28
- gem.add_dependency "grpc-google-iam-v1", ">= 0.6.10", "< 2.0"
26
+ <%- gem.dependency_list.each do |name, requirements| -%>
27
+ gem.add_dependency <%= name.inspect %>, <%= requirements.map { |v| v.inspect }.join ", " %>
29
28
  <%- end -%>
30
29
 
31
30
  gem.add_development_dependency "google-style", "~> 1.24.0"
32
- gem.add_development_dependency "minitest", "~> 5.10"
31
+ gem.add_development_dependency "minitest", "~> 5.14"
32
+ gem.add_development_dependency "minitest-focus", "~> 1.1"
33
+ gem.add_development_dependency "minitest-rg", "~> 5.2"
33
34
  gem.add_development_dependency "rake", ">= 12.0"
34
35
  gem.add_development_dependency "redcarpet", "~> 3.0"
35
36
  gem.add_development_dependency "simplecov", "~> 0.18"
@@ -10,6 +10,7 @@ RuboCop::RakeTask.new
10
10
  require "rake/testtask"
11
11
  desc "Run tests."
12
12
  Rake::TestTask.new do |t|
13
+ t.libs << "test"
13
14
  t.test_files = FileList["test/**/*_test.rb"]
14
15
  t.warning = false
15
16
  end