gapic-generator 0.4.2 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/gem_templates/dockerfile.erb +1 -1
  4. data/gem_templates/entrypoint.erb +1 -0
  5. data/lib/gapic/file_formatter.rb +0 -1
  6. data/lib/gapic/generator/version.rb +1 -1
  7. data/lib/gapic/generators/default_generator.rb +16 -14
  8. data/lib/gapic/{path_template.rb → path_pattern.rb} +9 -8
  9. data/lib/gapic/path_pattern/parser.rb +146 -0
  10. data/lib/gapic/path_pattern/pattern.rb +80 -0
  11. data/lib/gapic/path_pattern/segment.rb +276 -0
  12. data/lib/gapic/presenters/field_presenter.rb +12 -0
  13. data/lib/gapic/presenters/gem_presenter.rb +39 -3
  14. data/lib/gapic/presenters/method_presenter.rb +10 -5
  15. data/lib/gapic/presenters/package_presenter.rb +4 -3
  16. data/lib/gapic/presenters/resource_presenter.rb +48 -36
  17. data/lib/gapic/presenters/service_presenter.rb +18 -12
  18. data/lib/gapic/runner.rb +3 -1
  19. data/lib/gapic/schema/api.rb +7 -0
  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/gemspec.erb +7 -6
  26. data/templates/default/gem/rakefile.erb +1 -0
  27. data/templates/default/gem/test_helper.erb +8 -0
  28. data/templates/default/lib/_service.erb +2 -0
  29. data/templates/default/service/client/_client.erb +4 -1
  30. data/templates/default/service/client/_config.erb +15 -11
  31. data/templates/default/service/client/_operations.erb +2 -0
  32. data/templates/default/service/client/resource/_doc.erb +1 -1
  33. data/templates/default/service/client/resource/_multi.erb +2 -5
  34. data/templates/default/service/client/resource/_single.erb +1 -2
  35. data/templates/default/service/test/_resource.erb +16 -0
  36. data/templates/default/service/test/client.erb +2 -5
  37. data/templates/default/service/test/client_operations.erb +2 -5
  38. data/templates/default/service/test/client_paths.erb +15 -0
  39. data/templates/default/service/test/method/_bidi.erb +6 -0
  40. data/templates/default/service/test/method/_client.erb +6 -0
  41. data/templates/default/service/test/method/_normal.erb +6 -0
  42. data/templates/default/service/test/method/_server.erb +6 -0
  43. metadata +13 -7
  44. data/lib/gapic/path_template/parser.rb +0 -83
  45. data/lib/gapic/path_template/segment.rb +0 -67
@@ -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,8 +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"
18
- require "ostruct"
17
+ require "gapic/path_pattern"
19
18
  require "active_support/inflector"
20
19
 
21
20
  module Gapic
@@ -28,20 +27,10 @@ module Gapic
28
27
  def initialize resource
29
28
  @resource = resource
30
29
 
31
- @patterns = resource.pattern.map do |template|
32
- segments = Gapic::PathTemplate.parse template
33
- OpenStruct.new(
34
- template: template,
35
- segments: segments,
36
- arguments: arguments_for(segments),
37
- path_string: path_string_for(segments)
38
- )
39
- end
30
+ @patterns = resource.pattern.map { |pattern| PatternPresenter.new pattern }
40
31
 
41
32
  # Keep only patterns that can be used to create path helpers
42
- @patterns.reject! do |pattern|
43
- named_arg_patterns?(pattern.segments) || positional_args?(pattern.segments)
44
- end
33
+ @patterns.filter!(&:useful_for_helpers?)
45
34
  end
46
35
 
47
36
  def name
@@ -60,33 +49,56 @@ module Gapic
60
49
  "#{ActiveSupport::Inflector.underscore name}_path"
61
50
  end
62
51
 
63
- private
52
+ ##
53
+ # A presenter for a particular pattern
54
+ #
55
+ class PatternPresenter
56
+ def initialize pattern_string
57
+ @pattern = pattern_string
58
+ @parsed_pattern = Gapic::PathPattern.parse pattern_string
59
+ @path_string = build_path_string
60
+ end
64
61
 
65
- def arguments_for segments
66
- arg_segments(segments).map(&:name)
67
- end
62
+ attr_reader :pattern, :path_string
68
63
 
69
- def arg_segments segments
70
- segments.select { |segment| segment.is_a? Gapic::PathTemplate::Segment }
71
- end
64
+ def useful_for_helpers?
65
+ !@parsed_pattern.positional_segments? && !@parsed_pattern.nontrivial_pattern_segments?
66
+ end
72
67
 
73
- def path_string_for segments
74
- segments.map do |segment|
75
- if segment.is_a? Gapic::PathTemplate::Segment
76
- "\#{#{segment.name}}"
77
- else
78
- # Should be a String
79
- segment
80
- end
81
- end.join
82
- end
68
+ def arguments
69
+ @parsed_pattern.arguments
70
+ end
83
71
 
84
- def positional_args? segments
85
- arg_segments(segments).any?(&:positional?)
86
- end
72
+ def formal_arguments
73
+ @parsed_pattern.arguments.map { |name| "#{name}:" }.join ", "
74
+ end
75
+
76
+ def arguments_key
77
+ @parsed_pattern.arguments.sort.join ":"
78
+ end
79
+
80
+ def arguments_with_dummy_values
81
+ @parsed_pattern.arguments.each_with_index.map { |name, index| "#{name}: \"value#{index}\"" }.join ", "
82
+ end
87
83
 
88
- def named_arg_patterns? segments
89
- arg_segments(segments).any?(&:pattern)
84
+ def expected_path_for_dummy_values
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
91
+ else
92
+ segment.pattern
93
+ end
94
+ end.join "/"
95
+ end
96
+
97
+ private
98
+
99
+ def build_path_string
100
+ @parsed_pattern.segments.map(&:path_string).join "/"
101
+ end
90
102
  end
91
103
  end
92
104
  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
@@ -89,7 +90,7 @@ module Gapic
89
90
  end
90
91
 
91
92
  def name
92
- @service.name
93
+ @api.fix_service_name @service.name
93
94
  end
94
95
 
95
96
  # The namespace of the protos. This may be different from the client
@@ -102,7 +103,7 @@ module Gapic
102
103
  end
103
104
 
104
105
  def proto_service_name_full
105
- name_full = "#{proto_namespace}::#{name}"
106
+ name_full = "#{proto_namespace}::#{@service.name}"
106
107
  @api.override_proto_namespaces? ? fix_namespace(@api, name_full) : name_full
107
108
  end
108
109
 
@@ -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,16 +196,16 @@ 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
206
  default_config(:oauth_scopes)
201
207
  end
202
208
 
203
- def client_proto_name
204
- @service.address.join "."
205
- end
206
-
207
209
  def credentials_name
208
210
  "Credentials"
209
211
  end
@@ -272,6 +274,10 @@ module Gapic
272
274
  service_file_path.sub ".rb", "_test.rb"
273
275
  end
274
276
 
277
+ def test_paths_file_path
278
+ service_file_path.sub ".rb", "_paths_test.rb"
279
+ end
280
+
275
281
  def test_client_operations_file_path
276
282
  service_file_path.sub ".rb", "_operations_test.rb"
277
283
  end
@@ -314,7 +320,7 @@ module Gapic
314
320
 
315
321
  def lro_service
316
322
  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?
323
+ return ServicePresenter.new @gem_presenter, @api, lro.services.first, parent_service: self unless lro.nil?
318
324
  end
319
325
 
320
326
  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.
@@ -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
@@ -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