gapic-generator 0.6.0 → 0.6.5

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/gem_templates/entrypoint.erb +1 -0
  4. data/gem_templates/gemspec.erb +0 -1
  5. data/lib/gapic/file_formatter.rb +1 -2
  6. data/lib/gapic/generator/version.rb +1 -1
  7. data/lib/gapic/{path_template.rb → path_pattern.rb} +9 -8
  8. data/lib/gapic/path_pattern/parser.rb +146 -0
  9. data/lib/gapic/path_pattern/pattern.rb +80 -0
  10. data/lib/gapic/path_pattern/segment.rb +276 -0
  11. data/lib/gapic/presenters/field_presenter.rb +12 -0
  12. data/lib/gapic/presenters/gem_presenter.rb +16 -2
  13. data/lib/gapic/presenters/method_presenter.rb +7 -3
  14. data/lib/gapic/presenters/resource_presenter.rb +23 -31
  15. data/lib/gapic/presenters/service_presenter.rb +2 -1
  16. data/lib/gapic/runner.rb +3 -1
  17. data/lib/gapic/schema/api.rb +17 -1
  18. data/lib/gapic/schema/wrappers.rb +24 -20
  19. data/lib/gapic/uri_template.rb +36 -0
  20. data/lib/gapic/uri_template/parser.rb +50 -0
  21. data/lib/google/protobuf/compiler/plugin.pb.rb +5 -1
  22. data/lib/google/protobuf/descriptor.pb.rb +1 -0
  23. data/templates/default/gem/gemfile.erb +0 -3
  24. data/templates/default/gem/readme.erb +1 -1
  25. data/templates/default/service/client/resource/_doc.erb +1 -1
  26. data/templates/default/service/client/resource/_multi.erb +4 -0
  27. data/templates/default/service/test/client.erb +1 -3
  28. data/templates/default/service/test/client_operations.erb +1 -3
  29. data/templates/default/service/test/client_paths.erb +1 -3
  30. data/templates/default/service/test/method/_bidi.erb +10 -2
  31. data/templates/default/service/test/method/_client.erb +10 -2
  32. data/templates/default/service/test/method/_normal.erb +6 -0
  33. data/templates/default/service/test/method/_server.erb +9 -1
  34. data/templates/default/service/test/method/_setup.erb +2 -2
  35. metadata +10 -21
  36. data/lib/gapic/path_template/parser.rb +0 -83
  37. 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
@@ -48,6 +48,10 @@ module Gapic
48
48
  end
49
49
  end
50
50
 
51
+ def first_non_common_service
52
+ services.find { |service| service.common_service_delegate.nil? }
53
+ end
54
+
51
55
  def proto_files
52
56
  @proto_files ||= begin
53
57
  files = @api.files
@@ -134,7 +138,17 @@ module Gapic
134
138
  end
135
139
 
136
140
  def api_id
137
- gem_config :api_id
141
+ raw_id = gem_config :api_id
142
+ return nil unless raw_id
143
+ raw_id.include?(".") ? raw_id : "#{raw_id}.googleapis.com"
144
+ end
145
+
146
+ def api_shortname
147
+ gem_config :api_shortname
148
+ end
149
+
150
+ def issue_tracker_url
151
+ gem_config :issue_tracker_url
138
152
  end
139
153
 
140
154
  def free_tier?
@@ -164,7 +178,7 @@ module Gapic
164
178
  end
165
179
 
166
180
  def dependencies
167
- deps = { "gapic-common" => "~> 0.2" }
181
+ deps = { "gapic-common" => "~> 0.3" }
168
182
  deps["grpc-google-iam-v1"] = [">= 0.6.10", "< 2.0"] if iam_dependency?
169
183
  extra_deps = gem_config :extra_dependencies
170
184
  deps.merge! extra_deps if extra_deps
@@ -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
 
@@ -92,6 +92,11 @@ module Gapic
92
92
  have_oneof = []
93
93
 
94
94
  @method.input.fields.each do |field|
95
+ unless field.oneof?
96
+ selected_fields << field
97
+ next
98
+ end
99
+
95
100
  idx = field.oneof_index
96
101
  selected_fields << field unless have_oneof.include? idx
97
102
  have_oneof << idx
@@ -194,8 +199,7 @@ module Gapic
194
199
  # @return [Array<String>] The segment key names.
195
200
  #
196
201
  def routing_params
197
- segments = Gapic::PathTemplate.parse method_path
198
- segments.select { |s| s.is_a? Gapic::PathTemplate::Segment }.map(&:name)
202
+ Gapic::UriTemplate.parse_arguments method_path
199
203
  end
200
204
 
201
205
  def routing_params?
@@ -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
@@ -203,7 +203,8 @@ module Gapic
203
203
  def client_scopes
204
204
  common_service_delegate&.client_scopes ||
205
205
  @service.scopes ||
206
- default_config(:oauth_scopes)
206
+ default_config(:oauth_scopes) ||
207
+ []
207
208
  end
208
209
 
209
210
  def credentials_name
@@ -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.
@@ -44,14 +44,18 @@ module Gapic
44
44
  #
45
45
  # @param request [Google::Protobuf::Compiler::CodeGeneratorRequest]
46
46
  # The request object.
47
- def initialize request
47
+ # @param error_output [IO] An IO to write any errors/warnings to.
48
+ # @param configuration [Hash] Optional override of configuration.
49
+ def initialize request, error_output: STDERR, configuration: nil
48
50
  @request = request
49
51
  loader = Loader.new
50
52
  @files = request.proto_file.map do |fd|
51
53
  loader.load_file fd, request.file_to_generate.include?(fd.name)
52
54
  end
53
55
  @files.each { |f| f.parent = self }
56
+ @configuration = configuration
54
57
  @resource_types = analyze_resources
58
+ sanity_checks error_output
55
59
  end
56
60
 
57
61
  def containing_api
@@ -295,6 +299,18 @@ module Gapic
295
299
 
296
300
  private
297
301
 
302
+ # Perform a variety of sanity checks on the data, and prints errors to
303
+ # the given output as appropriate.
304
+ #
305
+ # @param output [IO] Stream to write outputs to.
306
+ def sanity_checks output
307
+ addrs = services.map { |service| service.address.join "." }
308
+ configuration[:common_services]&.each do |k, v|
309
+ output.puts "WARNING: configured common service #{k} is not present" unless addrs.include? k
310
+ output.puts "WARNING: configured common service delegate #{v} is not present" unless addrs.include? v
311
+ end
312
+ end
313
+
298
314
  # Does a pre-analysis of all resources defined in the job. This has
299
315
  # two effects:
300
316
  # * Side effect: each resource has its parent_resources field set.
@@ -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
@@ -0,0 +1,50 @@
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
+ module UriTemplate
19
+ # A URI template parser.
20
+ # see https://tools.ietf.org/html/rfc6570 URI Template
21
+ #
22
+ # @!attribute [r] path_pattern
23
+ # @return [String] The path pattern to be parsed.
24
+ # @!attribute [r] segments
25
+ # @return [Array<Segment|String>] The segments of the parsed path pattern.
26
+ module Parser
27
+ # @private
28
+ # /((?<positional>\*\*?)|{(?<name>[^\/]+?)(?:=(?<template>.+?))?})/
29
+ URI_TEMPLATE = %r{
30
+ (
31
+ (?<positional>\*\*?)
32
+ |
33
+ {(?<name>[^\/]+?)(?:=(?<template>.+?))?}
34
+ )
35
+ }x.freeze
36
+
37
+ def self.parse_arguments uri_template
38
+ arguments = []
39
+
40
+ while (match = URI_TEMPLATE.match uri_template)
41
+ # The String before the match needs to be added to the segments
42
+ arguments << match[:name] if match[:name]
43
+ uri_template = match.post_match
44
+ end
45
+
46
+ arguments
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,7 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  ##
4
- # This file is auto-generated. DO NOT EDIT!
4
+ # This file was auto-generated initially but now is hand-edited to add support
5
+ # for response features and proto3_optional
5
6
  #
6
7
  require 'protobuf'
7
8
 
@@ -54,6 +55,8 @@ module Google
54
55
  end
55
56
 
56
57
  class CodeGeneratorResponse
58
+ FEATURE_PROTO3_OPTIONAL = 1
59
+
57
60
  class File
58
61
  optional :string, :name, 1
59
62
  optional :string, :insertion_point, 2
@@ -61,6 +64,7 @@ module Google
61
64
  end
62
65
 
63
66
  optional :string, :error, 1
67
+ optional :int32, :supported_features, 2
64
68
  repeated ::Google::Protobuf::Compiler::CodeGeneratorResponse::File, :file, 15
65
69
  end
66
70