gapic-generator 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 141fbba25c93dca9ccac5c4a380f7a0f8c1c1643ef2e9517fbb158ba92db822c
4
- data.tar.gz: c61466f199a4d34b6c1fefea9aa8773abc7d9514dfb232385a1e6806e49140f2
3
+ metadata.gz: 6eb09d3958e2bf3212a940df300ab29228dabdb7dabc31b1d9755eddee129c5b
4
+ data.tar.gz: e9431a7bc6f8680553e0bd682d68cdf6ec5fc61a6c564fec5c074f4884d362c9
5
5
  SHA512:
6
- metadata.gz: 1cefa5cb936a4d9f211c0af9f03a9bcbd4ba76f35417cc3a1723164c949dc93b0f9f8be3602ac882d19c2a1109eed7b47150f4be4587ab5d5a368d7942df14f5
7
- data.tar.gz: eab763dd18a81db68af29cc55e54b69f7f8fe504bca56aa93925a66e0c8f548335a4700c0cb89cb13aef65f5de7d640dc8dc0a704190e6a06f7ecdaeb294b065
6
+ metadata.gz: 554bdbb8d1b6ca6dbfb646656cb91dc5f1080d60e8e7103771ca8e3352f09e33a0b9ef3edd86547c173cfc98e18d45da1be8b9648aef40525b1bfb13c5579d62
7
+ data.tar.gz: c998693373a980357d17d540fdbaa891959666bfb2b2dd12b2843eb9b8df0bca1808259305c25614a3951f695b004fa28b862888e1e9e4fa706ce6cfcd2b4f5f
@@ -1,5 +1,14 @@
1
1
  # Release History for gapic-generator
2
2
 
3
+ ### 0.4.0 / 2020-04-20
4
+
5
+ * Support generating clients of "common" interfaces by delegating to another service config.
6
+ * Added an accessor for the long-running-operation client from the main client.
7
+ * Generate tests for the configure method and operations client accessor.
8
+ * Prevent generation of RPC or factory methods with reserved names.
9
+ * Fixed: LRO clients weren't inheriting custom endpoints from the main client.
10
+ * Fixed: Cross-references weren't interpreted if the text included backticks, spaces, or hyphens.
11
+
3
12
  ### 0.3.3 / 2020-04-13
4
13
 
5
14
  * Fix cross-reference links to multi-word enum values.
@@ -22,7 +22,7 @@ module Gapic
22
22
  #
23
23
  module FormattingUtils
24
24
  @brace_detector = /\A(?<pre>[^`]*(`[^`]*`[^`]*)*[^`\\])?\{(?<inside>[^\s][^}]*)\}(?<post>.*)\z/m
25
- @xref_detector = /\A(?<pre>[^`]*(`[^`]*`[^`]*)*)?\[(?<text>[\w\.]+)\]\[(?<addr>[\w\.]+)\](?<post>.*)\z/m
25
+ @xref_detector = /\A(?<pre>[^`]*(`[^`]*`[^`]*)*)?\[(?<text>[\w\. `-]+)\]\[(?<addr>[\w\.]+)\](?<post>.*)\z/m
26
26
  @list_element_detector = /\A\s*(\*|\+|-|[0-9a-zA-Z]+\.)\s/
27
27
 
28
28
  class << self
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Gapic
18
18
  module Generator
19
- VERSION = "0.3.3"
19
+ VERSION = "0.4.0"
20
20
  end
21
21
  end
@@ -16,6 +16,7 @@
16
16
 
17
17
  require "active_support/inflector"
18
18
  require "gapic/path_template"
19
+ require "gapic/ruby_info"
19
20
  require "gapic/helpers/namespace_helper"
20
21
 
21
22
  module Gapic
@@ -36,7 +37,11 @@ module Gapic
36
37
  end
37
38
 
38
39
  def name
39
- ActiveSupport::Inflector.underscore @method.name
40
+ @name ||= begin
41
+ candidate = ActiveSupport::Inflector.underscore @method.name
42
+ candidate = "call_#{candidate}" if Gapic::RubyInfo.excluded_method_names.include? candidate
43
+ candidate
44
+ end
40
45
  end
41
46
 
42
47
  def kind
@@ -53,10 +53,17 @@ module Gapic
53
53
  namespace.split("::").last
54
54
  end
55
55
 
56
+ # Services whose clients should be generated in this package namespace.
56
57
  def services
57
58
  @services ||= begin
58
59
  files = @api.generate_files.select { |f| f.package == @package }
59
- files.map(&:services).flatten.map { |s| ServicePresenter.new @api, s }
60
+ services = files.map(&:services).flatten
61
+ # Omit common services in this package. Common service clients do not
62
+ # go into their own package.
63
+ normal_services = services.select { |s| @api.delegate_service_for(s).nil? }
64
+ # But include common services that delegate to normal services in this package.
65
+ common_services = normal_services.flat_map { |s| @api.common_services_for s }
66
+ (normal_services + common_services).map { |s| ServicePresenter.new @api, s }
60
67
  end
61
68
  end
62
69
 
@@ -55,7 +55,25 @@ module Gapic
55
55
  @service.address
56
56
  end
57
57
 
58
+ # Returns a presenter for this service's delegate (if it is a common service)
59
+ # otherwise returns `nil`.
60
+ def common_service_delegate
61
+ unless defined? @common_service_delegate
62
+ delegate = @api.delegate_service_for @service
63
+ @common_service_delegate = delegate ? ServicePresenter.new(@api, delegate) : nil
64
+ end
65
+ @common_service_delegate
66
+ end
67
+
68
+ # The namespace of the client. Normally this is the version module. This
69
+ # may be different from the proto namespace for a common service.
58
70
  def namespace
71
+ # If this service is a common service, its client should go into its
72
+ # delegate's namespace rather than its own. For example, KMS includes
73
+ # the common IAMPolicy service, but that service's client should go
74
+ # into the KMS namespace.
75
+ return common_service_delegate.namespace if common_service_delegate
76
+
59
77
  return @service.ruby_package if @service.ruby_package.present?
60
78
 
61
79
  namespace = ruby_namespace_for_address @service.address[0...-1]
@@ -74,12 +92,22 @@ module Gapic
74
92
  @service.name
75
93
  end
76
94
 
95
+ # The namespace of the protos. This may be different from the client
96
+ # namespace for a common service.
97
+ def proto_namespace
98
+ return @service.ruby_package if @service.ruby_package.present?
99
+
100
+ namespace = ruby_namespace_for_address @service.address[0...-1]
101
+ @api.override_proto_namespaces? ? fix_namespace(@api, namespace) : namespace
102
+ end
103
+
77
104
  def proto_service_name_full
78
- fix_namespace @api, "#{namespace}::#{name}"
105
+ name_full = "#{proto_namespace}::#{name}"
106
+ @api.override_proto_namespaces? ? fix_namespace(@api, name_full) : name_full
79
107
  end
80
108
 
81
109
  def module_name
82
- proto_service_name_full.split("::").last
110
+ service_name_full.split("::").last
83
111
  end
84
112
 
85
113
  def proto_service_file_path
@@ -110,6 +138,10 @@ module Gapic
110
138
  "#{proto_service_name_full}::Stub"
111
139
  end
112
140
 
141
+ def service_name_full
142
+ fix_namespace @api, "#{namespace}::#{name}"
143
+ end
144
+
113
145
  def service_file_path
114
146
  service_require + ".rb"
115
147
  end
@@ -123,7 +155,7 @@ module Gapic
123
155
  end
124
156
 
125
157
  def service_require
126
- ruby_file_path @api, proto_service_name_full
158
+ ruby_file_path @api, service_name_full
127
159
  end
128
160
 
129
161
  def client_name
@@ -131,7 +163,7 @@ module Gapic
131
163
  end
132
164
 
133
165
  def client_name_full
134
- fix_namespace @api, "#{proto_service_name_full}::#{client_name}"
166
+ fix_namespace @api, "#{service_name_full}::#{client_name}"
135
167
  end
136
168
 
137
169
  def create_client_call
@@ -155,12 +187,17 @@ module Gapic
155
187
  end
156
188
 
157
189
  def client_endpoint
158
- return @parent_service.client_endpoint if @parent_service
159
- @service.host || default_config(:default_host) || "localhost"
190
+ @parent_service&.client_endpoint ||
191
+ common_service_delegate&.client_endpoint ||
192
+ @service.host ||
193
+ default_config(:default_host) ||
194
+ "localhost"
160
195
  end
161
196
 
162
197
  def client_scopes
163
- @service.scopes || default_config(:oauth_scopes)
198
+ common_service_delegate&.client_scopes ||
199
+ @service.scopes ||
200
+ default_config(:oauth_scopes)
164
201
  end
165
202
 
166
203
  def client_proto_name
@@ -172,7 +209,7 @@ module Gapic
172
209
  end
173
210
 
174
211
  def credentials_name_full
175
- fix_namespace @api, "#{proto_service_name_full}::#{credentials_name}"
212
+ fix_namespace @api, "#{service_name_full}::#{credentials_name}"
176
213
  end
177
214
 
178
215
  def credentials_class_xref
@@ -200,7 +237,7 @@ module Gapic
200
237
  end
201
238
 
202
239
  def helpers_require
203
- ruby_file_path @api, "#{proto_service_name_full}::Helpers"
240
+ ruby_file_path @api, "#{service_name_full}::Helpers"
204
241
  end
205
242
 
206
243
  def references
@@ -216,7 +253,7 @@ module Gapic
216
253
  end
217
254
 
218
255
  def paths_name_full
219
- fix_namespace @api, "#{proto_service_name_full}::#{paths_name}"
256
+ fix_namespace @api, "#{service_name_full}::#{paths_name}"
220
257
  end
221
258
 
222
259
  def paths_file_path
@@ -228,7 +265,7 @@ module Gapic
228
265
  end
229
266
 
230
267
  def paths_require
231
- ruby_file_path @api, "#{proto_service_name_full}::#{paths_name}"
268
+ ruby_file_path @api, "#{service_name_full}::#{paths_name}"
232
269
  end
233
270
 
234
271
  def test_client_file_path
@@ -260,7 +297,7 @@ module Gapic
260
297
  end
261
298
 
262
299
  def operations_name_full
263
- fix_namespace @api, "#{proto_service_name_full}::#{operations_name}"
300
+ fix_namespace @api, "#{service_name_full}::#{operations_name}"
264
301
  end
265
302
 
266
303
  def operations_file_path
@@ -272,7 +309,7 @@ module Gapic
272
309
  end
273
310
 
274
311
  def operations_require
275
- ruby_file_path @api, "#{proto_service_name_full}::#{operations_name}"
312
+ ruby_file_path @api, "#{service_name_full}::#{operations_name}"
276
313
  end
277
314
 
278
315
  def lro_service
@@ -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
@@ -202,7 +202,7 @@ module Gapic
202
202
  config = config_file ? YAML.load_file(config_file) : {}
203
203
  protoc_options.each do |k, v|
204
204
  next if k == "configuration"
205
- branch = key_to_str(k).split(".").reverse.inject(v) { |m, s| { str_to_key(s) => m } }
205
+ branch = parse_key(key_to_str(k)).reverse.inject(v) { |m, s| { str_to_key(s) => m } }
206
206
  config = deep_merge config, branch
207
207
  end
208
208
  config
@@ -225,6 +225,21 @@ module Gapic
225
225
  configuration[:generate_path_helpers_output] ||= false
226
226
  end
227
227
 
228
+ # Whether the override_proto_namespaces parameter was given in the configuration
229
+ def override_proto_namespaces_defined?
230
+ configuration.key? :override_proto_namespaces
231
+ end
232
+
233
+ # Sets the override_proto_namespaces parameter in the configuration
234
+ def override_proto_namespaces= value
235
+ configuration[:override_proto_namespaces] = value
236
+ end
237
+
238
+ # Whether namespace overrides apply to proto/grpc class references
239
+ def override_proto_namespaces?
240
+ configuration[:override_proto_namespaces] ||= false
241
+ end
242
+
228
243
  # Raw parsed json of the combined grpc service config files if provided
229
244
  # or an empty hash if no config was provided
230
245
  def grpc_service_config_raw
@@ -249,6 +264,28 @@ module Gapic
249
264
  @resource_types[resource_type]
250
265
  end
251
266
 
267
+ # Given a service, find all common services that use it as a delegate.
268
+ def common_services_for delegate
269
+ @delegate_to_common ||= begin
270
+ (configuration[:common_services] || {}).each_with_object({}) do |(c, d), mapping|
271
+ (mapping[d] ||= []) << c
272
+ end
273
+ end
274
+ all_services = services
275
+ @delegate_to_common.fetch(delegate.address.join("."), []).map do |addr|
276
+ addr = addr.split "."
277
+ all_services.find { |s| s.address == addr }
278
+ end.compact.uniq
279
+ end
280
+
281
+ # Given a common service, return its delegate.
282
+ def delegate_service_for common
283
+ addr = (configuration[:common_services] || {})[common.address.join "."]
284
+ return nil unless addr
285
+ addr = addr.split "."
286
+ services.find { |s| s.address == addr }
287
+ end
288
+
252
289
  private
253
290
 
254
291
  # Does a pre-analysis of all resources defined in the job. This has
@@ -291,6 +328,8 @@ module Gapic
291
328
  end
292
329
  end
293
330
 
331
+ # Parse a comma-delimited list of equals-delimited lists of strings, while
332
+ # mapping backslash-escaped commas and equal signs to literal characters.
294
333
  def parse_parameter str
295
334
  str.scan(/\\.|,|=|[^\\,=]+/)
296
335
  .each_with_object([[String.new]]) do |tok, arr|
@@ -307,6 +346,22 @@ module Gapic
307
346
  end
308
347
  end
309
348
 
349
+ # split the string on periods, but map backslash-escaped periods to
350
+ # literal periods.
351
+ def parse_key str
352
+ str.scan(/\.|\\.|[^\.\\]+/)
353
+ .each_with_object([String.new]) do |tok, arr|
354
+ if tok == "."
355
+ arr.append String.new
356
+ elsif tok.start_with? "\\"
357
+ arr.last << tok[1]
358
+ else
359
+ arr.last << tok
360
+ end
361
+ arr
362
+ end
363
+ end
364
+
310
365
  def str_to_key str
311
366
  str = str.to_s
312
367
  str.start_with?(":") ? str[1..-1].to_sym : str
@@ -2,5 +2,5 @@
2
2
  <%= render partial: "service/client/client",
3
3
  layout: "layouts/ruby",
4
4
  locals: { service: service,
5
- namespace: service.proto_service_name_full }
5
+ namespace: service.service_name_full }
6
6
  %>
@@ -105,6 +105,7 @@ class <%= service.client_name %>
105
105
  <%- if service.lro? -%>
106
106
  <%= service.lro_client_ivar %> = <%= service.operations_name %>.new do |config|
107
107
  config.credentials = credentials
108
+ config.endpoint = @config.endpoint
108
109
  end
109
110
 
110
111
  <%- end -%>
@@ -117,6 +118,15 @@ class <%= service.client_name %>
117
118
  )
118
119
  end
119
120
 
121
+ <%- if service.lro? -%>
122
+ ##
123
+ # Get the associated client for long-running operations.
124
+ #
125
+ # @return [<%= service.operations_name_full %>]
126
+ #
127
+ attr_reader :<%= service.lro_client_var %>
128
+
129
+ <%- end -%>
120
130
  # Service calls
121
131
  <%- service.methods.each do |method| -%>
122
132
 
@@ -2,5 +2,5 @@
2
2
  <%= render partial: "service/client/credentials",
3
3
  layout: "layouts/ruby",
4
4
  locals: { service: service,
5
- namespace: service.proto_service_name_full }
5
+ namespace: service.service_name_full }
6
6
  %>
@@ -2,5 +2,5 @@
2
2
  <%= render partial: "service/client/operations",
3
3
  layout: "layouts/ruby",
4
4
  locals: { service: service,
5
- namespace: service.proto_service_name_full }
5
+ namespace: service.service_name_full }
6
6
  %>
@@ -2,5 +2,5 @@
2
2
  <%= render partial: "service/client/paths",
3
3
  layout: "layouts/ruby",
4
4
  locals: { service: service,
5
- namespace: service.proto_service_name_full }
5
+ namespace: service.service_name_full }
6
6
  %>
@@ -17,8 +17,22 @@ class <%= service.client_name_full %>Test < Minitest::Test
17
17
  <% service.methods.each do |method| %>
18
18
  <%= indent render(partial: "service/test/method/#{method.kind}",
19
19
  locals: { method: method }), 2 %>
20
- <% if method != service.methods.last %>
21
20
 
22
21
  <% end %>
23
- <% end %>
22
+ <%= indent render(partial: "service/test/method/configure", locals: { service: service }), 2 %>
23
+ <%- if service.lro? -%>
24
+
25
+ def test_<%= service.lro_client_var %>
26
+ grpc_channel = GRPC::Core::Channel.new "localhost:8888", nil, :this_channel_is_insecure
27
+
28
+ client = nil
29
+ Gapic::ServiceStub.stub :new, nil do
30
+ client = <%= service.client_name_full =%>.new do |config|
31
+ config.credentials = grpc_channel
32
+ end
33
+ end
34
+
35
+ assert_kind_of <%= service.operations_name_full %>, client.<%= service.lro_client_var %>
36
+ end
37
+ <%- end -%>
24
38
  end
@@ -17,8 +17,8 @@ class <%= service.operations_name_full %>Test < Minitest::Test
17
17
  <% service.lro_service.methods.each do |method| %>
18
18
  <%= indent render(partial: "service/test/method/#{method.kind}",
19
19
  locals: { client_name_full: service.operations_name_full, method: method }), 2 %>
20
- <% if method != service.lro_service.methods.last %>
21
20
 
22
21
  <% end %>
23
- <% end %>
22
+ <%= indent render(partial: "service/test/method/configure",
23
+ locals: { service: service, client_name_full: service.operations_name_full }), 2 %>
24
24
  end
@@ -0,0 +1,19 @@
1
+ <%- assert_locals service -%>
2
+ <%- full_client_name = defined?(client_name_full) ? client_name_full : service.client_name_full -%>
3
+ def test_configure
4
+ grpc_channel = GRPC::Core::Channel.new "localhost:8888", nil, :this_channel_is_insecure
5
+
6
+ client = block_config = config = nil
7
+ Gapic::ServiceStub.stub :new, nil do
8
+ client = <%= full_client_name =%>.new do |config|
9
+ config.credentials = grpc_channel
10
+ end
11
+ end
12
+
13
+ config = client.configure do |c|
14
+ block_config = c
15
+ end
16
+
17
+ assert_same block_config, config
18
+ assert_kind_of <%= full_client_name %>::Configuration, config
19
+ 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.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ernest Landrito
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-04-13 00:00:00.000000000 Z
13
+ date: 2020-04-20 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: actionpack
@@ -233,6 +233,7 @@ files:
233
233
  - lib/gapic/presenters/sample_presenter.rb
234
234
  - lib/gapic/presenters/service_presenter.rb
235
235
  - lib/gapic/resource_lookup.rb
236
+ - lib/gapic/ruby_info.rb
236
237
  - lib/gapic/runner.rb
237
238
  - lib/gapic/schema.rb
238
239
  - lib/gapic/schema/api.rb
@@ -323,6 +324,7 @@ files:
323
324
  - templates/default/service/test/method/_assert_response.erb
324
325
  - templates/default/service/test/method/_bidi.erb
325
326
  - templates/default/service/test/method/_client.erb
327
+ - templates/default/service/test/method/_configure.erb
326
328
  - templates/default/service/test/method/_normal.erb
327
329
  - templates/default/service/test/method/_server.erb
328
330
  - templates/default/service/test/method/_setup.erb