gapic-generator 0.5.1 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
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