gapic-generator 0.5.1 → 0.6.4

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/gem_templates/dockerfile.erb +1 -1
  4. data/gem_templates/entrypoint.erb +1 -0
  5. data/gem_templates/gemspec.erb +0 -1
  6. data/lib/gapic/file_formatter.rb +1 -2
  7. data/lib/gapic/generator/version.rb +1 -1
  8. data/lib/gapic/generators/default_generator.rb +3 -3
  9. data/lib/gapic/{path_template.rb → path_pattern.rb} +9 -8
  10. data/lib/gapic/path_pattern/parser.rb +146 -0
  11. data/lib/gapic/path_pattern/pattern.rb +80 -0
  12. data/lib/gapic/path_pattern/segment.rb +276 -0
  13. data/lib/gapic/presenters/field_presenter.rb +12 -0
  14. data/lib/gapic/presenters/gem_presenter.rb +39 -3
  15. data/lib/gapic/presenters/method_presenter.rb +10 -5
  16. data/lib/gapic/presenters/package_presenter.rb +4 -3
  17. data/lib/gapic/presenters/resource_presenter.rb +23 -31
  18. data/lib/gapic/presenters/service_presenter.rb +14 -7
  19. data/lib/gapic/runner.rb +3 -1
  20. data/lib/gapic/schema/wrappers.rb +24 -20
  21. data/lib/gapic/uri_template.rb +36 -0
  22. data/lib/gapic/uri_template/parser.rb +50 -0
  23. data/lib/google/protobuf/compiler/plugin.pb.rb +5 -1
  24. data/lib/google/protobuf/descriptor.pb.rb +1 -0
  25. data/templates/default/gem/gemfile.erb +0 -3
  26. data/templates/default/gem/gemspec.erb +4 -5
  27. data/templates/default/lib/_service.erb +2 -0
  28. data/templates/default/service/client/_client.erb +2 -0
  29. data/templates/default/service/client/_config.erb +1 -1
  30. data/templates/default/service/client/resource/_doc.erb +1 -1
  31. data/templates/default/service/client/resource/_multi.erb +4 -0
  32. data/templates/default/service/test/client.erb +1 -3
  33. data/templates/default/service/test/client_operations.erb +1 -3
  34. data/templates/default/service/test/client_paths.erb +1 -3
  35. data/templates/default/service/test/method/_bidi.erb +10 -2
  36. data/templates/default/service/test/method/_client.erb +10 -2
  37. data/templates/default/service/test/method/_normal.erb +6 -0
  38. data/templates/default/service/test/method/_server.erb +9 -1
  39. data/templates/default/service/test/method/_setup.erb +2 -2
  40. metadata +10 -21
  41. data/lib/gapic/path_template/parser.rb +0 -83
  42. data/lib/gapic/path_template/segment.rb +0 -74
@@ -80,6 +80,10 @@ module Gapic
80
80
  @field.enum?
81
81
  end
82
82
 
83
+ def proto3_optional?
84
+ @field.proto3_optional?
85
+ end
86
+
83
87
  def repeated?
84
88
  @field.repeated?
85
89
  end
@@ -88,6 +92,14 @@ module Gapic
88
92
  @field.map?
89
93
  end
90
94
 
95
+ def oneof?
96
+ @field.oneof?
97
+ end
98
+
99
+ def oneof_name
100
+ @message.oneof_decl[@field.oneof_index].name
101
+ end
102
+
91
103
  protected
92
104
 
93
105
  def field_doc_types field, output
@@ -33,7 +33,7 @@ module Gapic
33
33
  def packages
34
34
  @packages ||= begin
35
35
  packages = @api.generate_files.map(&:package).uniq.sort
36
- packages.map { |p| PackagePresenter.new @api, p }.delete_if(&:empty?)
36
+ packages.map { |p| PackagePresenter.new self, @api, p }.delete_if(&:empty?)
37
37
  end
38
38
  end
39
39
 
@@ -44,7 +44,7 @@ module Gapic
44
44
  def services
45
45
  @services ||= begin
46
46
  files = @api.generate_files
47
- files.map(&:services).flatten.map { |s| ServicePresenter.new @api, s }
47
+ files.map(&:services).flatten.map { |s| ServicePresenter.new self, @api, s }
48
48
  end
49
49
  end
50
50
 
@@ -134,7 +134,17 @@ module Gapic
134
134
  end
135
135
 
136
136
  def api_id
137
- gem_config :api_id
137
+ raw_id = gem_config :api_id
138
+ return nil unless raw_id
139
+ raw_id.include?(".") ? raw_id : "#{raw_id}.googleapis.com"
140
+ end
141
+
142
+ def api_shortname
143
+ gem_config :api_shortname
144
+ end
145
+
146
+ def issue_tracker_url
147
+ gem_config :issue_tracker_url
138
148
  end
139
149
 
140
150
  def free_tier?
@@ -147,10 +157,36 @@ module Gapic
147
157
  gem_config(:yard_strict) != "false"
148
158
  end
149
159
 
160
+ def generic_endpoint?
161
+ gem_config(:generic_endpoint) == "true"
162
+ end
163
+
150
164
  def entrypoint_require
151
165
  packages.first.package_require
152
166
  end
153
167
 
168
+ def license_name
169
+ "MIT"
170
+ end
171
+
172
+ def extra_files
173
+ ["README.md", "LICENSE.md", ".yardopts"]
174
+ end
175
+
176
+ def dependencies
177
+ deps = { "gapic-common" => "~> 0.3" }
178
+ deps["grpc-google-iam-v1"] = [">= 0.6.10", "< 2.0"] if iam_dependency?
179
+ extra_deps = gem_config :extra_dependencies
180
+ deps.merge! extra_deps if extra_deps
181
+ deps
182
+ end
183
+
184
+ def dependency_list
185
+ dependencies.to_a
186
+ .map { |name, requirements| [name, Array(requirements)] }
187
+ .sort_by { |name, _requirements| name }
188
+ end
189
+
154
190
  private
155
191
 
156
192
  def gem_config key
@@ -15,7 +15,7 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require "active_support/inflector"
18
- require "gapic/path_template"
18
+ require "gapic/uri_template"
19
19
  require "gapic/ruby_info"
20
20
  require "gapic/helpers/namespace_helper"
21
21
 
@@ -27,13 +27,14 @@ module Gapic
27
27
  class MethodPresenter
28
28
  include Gapic::Helpers::NamespaceHelper
29
29
 
30
- def initialize api, method
30
+ def initialize service_presenter, api, method
31
+ @service_presenter = service_presenter
31
32
  @api = api
32
33
  @method = method
33
34
  end
34
35
 
35
36
  def service
36
- ServicePresenter.new @api, @method.parent
37
+ @service_presenter
37
38
  end
38
39
 
39
40
  def name
@@ -91,6 +92,11 @@ module Gapic
91
92
  have_oneof = []
92
93
 
93
94
  @method.input.fields.each do |field|
95
+ unless field.oneof?
96
+ selected_fields << field
97
+ next
98
+ end
99
+
94
100
  idx = field.oneof_index
95
101
  selected_fields << field unless have_oneof.include? idx
96
102
  have_oneof << idx
@@ -193,8 +199,7 @@ module Gapic
193
199
  # @return [Array<String>] The segment key names.
194
200
  #
195
201
  def routing_params
196
- segments = Gapic::PathTemplate.parse method_path
197
- segments.select { |s| s.is_a? Gapic::PathTemplate::Segment }.map(&:name)
202
+ Gapic::UriTemplate.parse_arguments method_path
198
203
  end
199
204
 
200
205
  def routing_params?
@@ -27,13 +27,14 @@ module Gapic
27
27
  include Gapic::Helpers::FilepathHelper
28
28
  include Gapic::Helpers::NamespaceHelper
29
29
 
30
- def initialize api, package
30
+ def initialize gem_presenter, api, package
31
+ @gem_presenter = gem_presenter
31
32
  @api = api
32
33
  @package = package
33
34
  end
34
35
 
35
36
  def gem
36
- GemPresenter.new @api
37
+ @gem_presenter
37
38
  end
38
39
 
39
40
  def name
@@ -63,7 +64,7 @@ module Gapic
63
64
  normal_services = services.select { |s| @api.delegate_service_for(s).nil? }
64
65
  # But include common services that delegate to normal services in this package.
65
66
  common_services = normal_services.flat_map { |s| @api.common_services_for s }
66
- (normal_services + common_services).map { |s| ServicePresenter.new @api, s }
67
+ (normal_services + common_services).map { |s| ServicePresenter.new @gem_presenter, @api, s }
67
68
  end
68
69
  end
69
70
 
@@ -14,7 +14,7 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- require "gapic/path_template"
17
+ require "gapic/path_pattern"
18
18
  require "active_support/inflector"
19
19
 
20
20
  module Gapic
@@ -27,7 +27,7 @@ module Gapic
27
27
  def initialize resource
28
28
  @resource = resource
29
29
 
30
- @patterns = resource.pattern.map { |template| PatternPresenter.new template }
30
+ @patterns = resource.pattern.map { |pattern| PatternPresenter.new pattern }
31
31
 
32
32
  # Keep only patterns that can be used to create path helpers
33
33
  @patterns.filter!(&:useful_for_helpers?)
@@ -53,59 +53,51 @@ module Gapic
53
53
  # A presenter for a particular pattern
54
54
  #
55
55
  class PatternPresenter
56
- def initialize template
57
- @template = template
58
- @segments = Gapic::PathTemplate.parse template
59
- @arguments = arg_segments.map(&:name)
56
+ def initialize pattern_string
57
+ @pattern = pattern_string
58
+ @parsed_pattern = Gapic::PathPattern.parse pattern_string
60
59
  @path_string = build_path_string
61
60
  end
62
61
 
63
- attr_reader :template, :segments, :arguments, :path_string
62
+ attr_reader :pattern, :path_string
64
63
 
65
64
  def useful_for_helpers?
66
- arg_segments.none?(&:nontrivial_pattern?) && arg_segments.none?(&:positional?)
65
+ !@parsed_pattern.positional_segments? && !@parsed_pattern.nontrivial_pattern_segments?
66
+ end
67
+
68
+ def arguments
69
+ @parsed_pattern.arguments
67
70
  end
68
71
 
69
72
  def formal_arguments
70
- arguments.map { |arg| "#{arg}:" }.join ", "
73
+ @parsed_pattern.arguments.map { |name| "#{name}:" }.join ", "
71
74
  end
72
75
 
73
76
  def arguments_key
74
- arguments.sort.join ":"
77
+ @parsed_pattern.arguments.sort.join ":"
75
78
  end
76
79
 
77
80
  def arguments_with_dummy_values
78
- arguments.each_with_index.map { |arg, index| "#{arg}: \"value#{index}\"" }.join ", "
81
+ @parsed_pattern.arguments.each_with_index.map { |name, index| "#{name}: \"value#{index}\"" }.join ", "
79
82
  end
80
83
 
81
84
  def expected_path_for_dummy_values
82
- index = -1
83
- segments.map do |segment|
84
- if segment.is_a? Gapic::PathTemplate::Segment
85
- index += 1
86
- "value#{index}"
85
+ index = 0
86
+ @parsed_pattern.segments.map do |segment|
87
+ if segment.provides_arguments?
88
+ segment_dummy_path = segment.expected_path_for_dummy_values index
89
+ index += segment.arguments.length
90
+ segment_dummy_path
87
91
  else
88
- # Should be a String
89
- segment
92
+ segment.pattern
90
93
  end
91
- end.join
94
+ end.join "/"
92
95
  end
93
96
 
94
97
  private
95
98
 
96
- def arg_segments
97
- segments.select { |segment| segment.is_a? Gapic::PathTemplate::Segment }
98
- end
99
-
100
99
  def build_path_string
101
- segments.map do |segment|
102
- if segment.is_a? Gapic::PathTemplate::Segment
103
- "\#{#{segment.name}}"
104
- else
105
- # Should be a String
106
- segment
107
- end
108
- end.join
100
+ @parsed_pattern.segments.map(&:path_string).join "/"
109
101
  end
110
102
  end
111
103
  end
@@ -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
 
@@ -60,7 +61,7 @@ module Gapic
60
61
  def common_service_delegate
61
62
  unless defined? @common_service_delegate
62
63
  delegate = @api.delegate_service_for @service
63
- @common_service_delegate = delegate ? ServicePresenter.new(@api, delegate) : nil
64
+ @common_service_delegate = delegate ? ServicePresenter.new(@gem_presenter, @api, delegate) : nil
64
65
  end
65
66
  @common_service_delegate
66
67
  end
@@ -187,6 +188,7 @@ module Gapic
187
188
  end
188
189
 
189
190
  def client_endpoint
191
+ return nil if generic_endpoint?
190
192
  @parent_service&.client_endpoint ||
191
193
  common_service_delegate&.client_endpoint ||
192
194
  @service.host ||
@@ -194,10 +196,15 @@ module Gapic
194
196
  "localhost"
195
197
  end
196
198
 
199
+ def generic_endpoint?
200
+ gem.generic_endpoint?
201
+ end
202
+
197
203
  def client_scopes
198
204
  common_service_delegate&.client_scopes ||
199
205
  @service.scopes ||
200
- default_config(:oauth_scopes)
206
+ default_config(:oauth_scopes) ||
207
+ []
201
208
  end
202
209
 
203
210
  def credentials_name
@@ -314,7 +321,7 @@ module Gapic
314
321
 
315
322
  def lro_service
316
323
  lro = @service.parent.parent.files.find { |file| file.name == "google/longrunning/operations.proto" }
317
- return ServicePresenter.new @api, lro.services.first, parent_service: self unless lro.nil?
324
+ return ServicePresenter.new @gem_presenter, @api, lro.services.first, parent_service: self unless lro.nil?
318
325
  end
319
326
 
320
327
  def config_channel_args
@@ -48,8 +48,10 @@ module Gapic
48
48
  output_files = generator.new(api).generate
49
49
 
50
50
  # Create and write the response
51
- Google::Protobuf::Compiler::CodeGeneratorResponse.new \
51
+ response = Google::Protobuf::Compiler::CodeGeneratorResponse.new \
52
52
  file: output_files
53
+ response.supported_features = Google::Protobuf::Compiler::CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL
54
+ response
53
55
  end
54
56
 
55
57
  # Run protoc generation.
@@ -15,6 +15,7 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require "gapic/formatting_utils"
18
+ require "gapic/path_pattern"
18
19
 
19
20
  module Gapic
20
21
  module Schema
@@ -654,6 +655,15 @@ module Gapic
654
655
  field_behavior.include? Google::Api::FieldBehavior::OPTIONAL
655
656
  end
656
657
 
658
+ # Denotes a field as a part of oneof.
659
+ # oneof_index is an int field so it'll be 0 by default for every field
660
+ # and an index in the message's oneof table for the oneof fields
661
+ # but since the indexes in the message's oneof table start with 0 as well
662
+ # we need this to determine whether the field is a part of the oneof
663
+ def oneof?
664
+ @descriptor.field? :oneof_index
665
+ end
666
+
657
667
  # Denotes a field as required. This indicates that the field **must** be
658
668
  # provided as part of the request, and failure to do so will cause an
659
669
  # error (usually `INVALID_ARGUMENT`).
@@ -730,7 +740,8 @@ module Gapic
730
740
  :default_value,
731
741
  :oneof_index,
732
742
  :json_name,
733
- :options
743
+ :options,
744
+ :proto3_optional?
734
745
  )
735
746
  end
736
747
 
@@ -761,30 +772,32 @@ module Gapic
761
772
  # @return [Array<Gapic::Schema::ResourceDescriptor>] The resource
762
773
  # descriptor.
763
774
  # @!attribute [r] parsed_patterns
764
- # @return [Array<Array<String>>] The normalized, segmented forms of the
765
- # patterns. Normalized means all ID segments are replaced by asterisks
775
+ # @return [Array<String>] The template form of the
776
+ # patterns. Template means all ID segments are replaced by asterisks
766
777
  # to remove non-structural differences due to different names being
767
- # used. Segmented means simply split on slashes.
778
+ # used.
768
779
  # For example, if a pattern is `"projects/{project}""`, the
769
- # corresponding parsed pattern would be `["projects", "*"]`.
780
+ # corresponding parsed pattern would be `"projects/*"]`.
781
+ # @!attribure [r] parsed_parent_patterns
782
+ # return [Array<String>] Parsed patterns for the expected parents.
770
783
  # @!attribute [r] parent_resources
771
784
  # @return [Array<Gapic::Schema::Resource>] Parent resources
772
785
  class Resource
773
786
  extend Forwardable
774
- attr_reader :descriptor, :parsed_patterns, :parent_resources
787
+ attr_reader :descriptor, :parsed_patterns, :parsed_parent_patterns, :parent_resources
775
788
  attr_accessor :parent
776
789
 
777
790
  # Initializes a resource object.
778
- # @param descriptor [Google::Protobuf::ResourceDescriptor] the protobuf
791
+ # @param descriptor [Google::Api::ResourceDescriptor] the protobuf
779
792
  # representation of this resource.
780
793
  def initialize descriptor
781
794
  @parent = nil
782
795
  @descriptor = descriptor
783
- @parsed_patterns = descriptor.pattern.map do |pattern|
784
- pattern.split("/").map do |segment|
785
- segment =~ %r{\{[^/\}]+(=[^\}]+)?\}} ? "*" : segment
786
- end.freeze
796
+ patterns = descriptor.pattern.map do |pattern|
797
+ Gapic::PathPattern.parse pattern
787
798
  end.freeze
799
+ @parsed_patterns = patterns.map(&:template).compact.uniq.freeze
800
+ @parsed_parent_patterns = patterns.map(&:parent_template).compact.uniq.freeze
788
801
  @parent_resources = []
789
802
  end
790
803
 
@@ -800,15 +813,6 @@ module Gapic
800
813
  parent&.containing_file
801
814
  end
802
815
 
803
- # Returns parsed patterns for the expected parents.
804
- # @return [Array<Array<String>>]
805
- def parsed_parent_patterns
806
- @parsed_patterns.map do |pat|
807
- parent = pat.last =~ /^\*\*?$/ ? pat[0...-2] : pat[0...-1]
808
- parent.empty? ? nil : parent
809
- end.compact.uniq
810
- end
811
-
812
816
  # @!method type
813
817
  # @return [String] the resource type string.
814
818
  # @!method pattern
@@ -0,0 +1,36 @@
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
+ require "gapic/uri_template/parser"
18
+
19
+ module Gapic
20
+ # TODO: Enter docs
21
+ # Dooooooooocs!!!
22
+ module UriTemplate
23
+ # Parse arguments from a URI template.
24
+ # @see https://tools.ietf.org/html/rfc6570 URI Template
25
+ #
26
+ # used to satisfy AIP-4222 Routing headers
27
+ # @see https://google.aip.dev/client-libraries/4222
28
+ #
29
+ # @param uri_template [String] The URI template to be parsed.
30
+ #
31
+ # @return [Array<String>] The arguments of the URI template.
32
+ def self.parse_arguments uri_template
33
+ Parser.parse_arguments uri_template
34
+ end
35
+ end
36
+ end