gapic-generator 0.6.0 → 0.6.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19f79c05f4e657a010e8f9663f1eefeadabd18ef4b456c137a8278bf8bb13a9e
4
- data.tar.gz: ebe4c8c756ebd1e18424eccffc986f92bcda6f694a50842ed394c7d62d91f252
3
+ metadata.gz: b063888cabf4893087dcefa274cb8ab5a9469a762fc3dbb34af2e143cb1bcce4
4
+ data.tar.gz: 589dc9fdf67d63dc25fe62537783e6305e4441f51b5caa2c94a5b1a161e71ab7
5
5
  SHA512:
6
- metadata.gz: 4a6689a12fcd02390d416ab8ada828f79e182e87a3230361fe32e3a8eea42d7555039b61c699903d25a5fb244c9db1857bbad1d816ea04e4de329d67c4359c74
7
- data.tar.gz: fac5801f38bb3fd92b871c2c5ab9b2d7ee7138d0947ffb0c9695bd21ea0561762fee5dc462de884b5182cbf4627c5c9148783474584b6cb4c9dc7727313f7f1c
6
+ metadata.gz: 07a03fd0adcc1640a37fa334883838aee76c124d2e5380a00d540751b3740e1b0f13d82a981ab35297c095df38620a0895bf4bb7bb5dbf1421c659e71cd92e85
7
+ data.tar.gz: 10269fc5c70542e1ae9ee1471eb6365c1669c741aa1ac03dbaf3b652cec2aee14801717589d1c45febc554b280cd8cd178ac19e02b1224b2692d1e98324142f6
@@ -1,5 +1,11 @@
1
1
  # Release History for gapic-generator
2
2
 
3
+ ### 0.6.1 / 2020-06-16
4
+
5
+ * Add auto-generated disclaimer to generated tests.
6
+ * Support shortname and issue tracker URL configs.
7
+ * Refactors and minor fixes around resource template parsing.
8
+
3
9
  ### 0.6.0 / 2020-06-02
4
10
 
5
11
  * Support for clients with generic endpoint and credentials.
@@ -26,7 +26,6 @@ module Gapic
26
26
  ##
27
27
  # Create a new file formatter object
28
28
  #
29
- # @param path_template [String] The URI path template to be parsed.
30
29
  def initialize configuration, files
31
30
  @configuration = configuration
32
31
  @files = format! configuration, files
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Gapic
18
18
  module Generator
19
- VERSION = "0.6.0"
19
+ VERSION = "0.6.1"
20
20
  end
21
21
  end
@@ -14,22 +14,23 @@
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/parser"
17
+ require "gapic/path_pattern/parser"
18
18
 
19
19
  module Gapic
20
20
  # TODO: Enter docs
21
21
  # Dooooooooocs!!!
22
- module PathTemplate
23
- # Parse a URI path template.
22
+ module PathPattern
23
+ # Parse a URI path pattern.
24
24
  #
25
- # @see https://tools.ietf.org/html/rfc6570 URI Template
25
+ # @see https://google.aip.dev/122 AIP-122 Resource names
26
+ # @see https://google.aip.dev/123 AIP-123 Resource types
26
27
  #
27
- # @param path_template [String] The URI path template to be parsed.
28
+ # @param path_pattern [String] The URI path template to be parsed.
28
29
  #
29
- # @return [Array<PathTemplate::Segment|String>] The segments of the URI
30
+ # @return [PathPattern::Pattern] The parsed pattern
30
31
  # path template.
31
- def self.parse path_template
32
- Parser.new(path_template).segments
32
+ def self.parse path_pattern
33
+ Parser.parse path_pattern
33
34
  end
34
35
  end
35
36
  end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 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/path_pattern/segment"
18
+ require "gapic/path_pattern/pattern"
19
+
20
+ module Gapic
21
+ module PathPattern
22
+ ##
23
+ # A path pattern parser.
24
+ # takes a pattern and transforms it into a collection of parsed segments
25
+ # @see https://google.aip.dev/122
26
+ # @see https://google.aip.dev/123
27
+ #
28
+ module Parser
29
+ ##
30
+ # @param path_pattern [String] The path pattern to be parsed
31
+ # @return [Gapic::PathPattern::Pattern]
32
+ def self.parse path_pattern
33
+ remainder = path_pattern.sub(%r{^/}, "").sub(%r{/$}, "")
34
+
35
+ segments = []
36
+ position = 0
37
+ until remainder.empty?
38
+ segment, position, remainder = parse_first_segment_with_position remainder, position
39
+ segments << segment
40
+ end
41
+
42
+ Pattern.new path_pattern, segments
43
+ end
44
+
45
+ # @private
46
+ def self.parse_first_segment_with_position url_pattern, position
47
+ # check for the wildcard segment -- either * or **
48
+ # wildcard segments are positional, so the position counter is used and updated
49
+ segment, remainder = try_capture_wildcard_segment url_pattern, position
50
+ return [segment, position + 1, remainder] if segment
51
+
52
+ # check for the complex resource id segment, e.g. {foo}-{bar}_{baz}
53
+ segment, remainder = try_capture_complex_resource_id_segment url_pattern
54
+ return [segment, position, remainder] if segment
55
+
56
+ # check for the simple resource id segment, e.g. {foo} or {foo=some/pattern/*}
57
+ segment, remainder = try_capture_simple_resource_id_segment url_pattern
58
+ return [segment, position, remainder] if segment
59
+
60
+ # if nothing else fits, it's the collection id segment
61
+ segment, remainder = capture_collection_id_segment url_pattern
62
+ [segment, position, remainder]
63
+ end
64
+
65
+ ##
66
+ # Tries to capture the first segment of the pattern as a wildcard segment
67
+ # The wildcard segment can be either * or **
68
+ # @private
69
+ def self.try_capture_wildcard_segment url_pattern, position
70
+ wildcard_capture_regex = %r{^(?<pattern>\*\*|\*)(?:/|$)}
71
+ return nil, url_pattern unless wildcard_capture_regex.match? url_pattern
72
+
73
+ match = wildcard_capture_regex.match url_pattern
74
+
75
+ wildcard_pattern = match[:pattern]
76
+
77
+ segment = PositionalSegment.new position, wildcard_pattern
78
+ remainder = match.post_match
79
+ [segment, remainder]
80
+ end
81
+
82
+ ##
83
+ # Tries to capture the first segment of the pattern as a complex resource id segment
84
+ # The pattern for the complex resource id segments is:
85
+ # {<name_first>}<separator>{<name_second>} etc, e.g. {foo}-{bar}_{baz}
86
+ # see AIP-4231 Parsing resource names, Complex resource ID path segments
87
+ # @private
88
+ def self.try_capture_complex_resource_id_segment url_pattern
89
+ complex_resource_id_regex =
90
+ %r/^(?<segment_pattern>{(?<name_first>[^\/}]+?)}(?:(?<separator>[_\-~\.]){(?<name_seq>[^\/}]+?)})+)(?:\/|$)/
91
+
92
+ return nil, url_pattern unless complex_resource_id_regex.match? url_pattern
93
+
94
+ match = complex_resource_id_regex.match url_pattern
95
+ segment_pattern = match[:segment_pattern]
96
+
97
+ resource_name_regex = %r/{(?<name>[^\/}]+?)}/
98
+ resource_names = segment_pattern.scan(resource_name_regex).flatten
99
+
100
+ segment = ResourceIdSegment.new :complex_resource_id, segment_pattern, resource_names
101
+ remainder = match.post_match
102
+ [segment, remainder]
103
+ end
104
+
105
+ ##
106
+ # Tries to capture the first segment of the pattern as a simple resource id segment
107
+ # The pattern for the simple resource id segments is:
108
+ # {<name>} or with an optional resource name pattern {<name>=<pattern>}
109
+ # e.g. {foo} or with an optional pattern, e.g. {foo=**} or {foo=bar}
110
+ # notably here the pattern between the = and } *can* contain the path separator /
111
+ # @private
112
+ def self.try_capture_simple_resource_id_segment url_pattern
113
+ simple_resource_id_regex =
114
+ %r/^(?<segment_pattern>{(?<resource_name>[^\/}]+?)(?:=(?<resource_pattern>.+?))?})(?:\/|$)/
115
+ return nil, url_pattern unless simple_resource_id_regex.match? url_pattern
116
+
117
+ match = simple_resource_id_regex.match url_pattern
118
+ segment_pattern = match[:segment_pattern]
119
+
120
+ resource_name = match[:resource_name]
121
+ resource_pattern = match[:resource_pattern] if match.names.include? "resource_pattern"
122
+ resource_patterns = resource_pattern.nil? ? [] : [resource_pattern]
123
+
124
+ segment = ResourceIdSegment.new :simple_resource_id, segment_pattern, [resource_name], resource_patterns
125
+ remainder = match.post_match
126
+ [segment, remainder]
127
+ end
128
+
129
+ ##
130
+ # Captures the first segment of the pattern as a collection id segment
131
+ # This is used as a catch-all, so the collection id segment can contain anything
132
+ # except the path separator /
133
+ # @private
134
+ def self.capture_collection_id_segment url_pattern
135
+ collection_id_regex = %r{^(?<collection_name>[^/]+?)(?:/|$)}
136
+ match = collection_id_regex.match url_pattern
137
+
138
+ collection_name = match[:collection_name]
139
+
140
+ segment = CollectionIdSegment.new collection_name
141
+ remainder = match.post_match
142
+ [segment, remainder]
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,80 @@
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/path_pattern/segment"
18
+
19
+ module Gapic
20
+ module PathPattern
21
+ ##
22
+ # A parsed pattern.
23
+ # @see https://google.aip.dev/122 AIP-122 Resource names
24
+ # @see https://google.aip.dev/123 AIP-123 Resource types
25
+ #
26
+ # @!attribute [r] path_pattern
27
+ # @return [String] The path pattern
28
+ # @!attribute [r] segments
29
+ # @return [Array<PositionalSegment|ResourceIdSegment|CollectionIdSegment>]
30
+ # The parsed segments of the path pattern
31
+ class Pattern
32
+ attr_reader :path_pattern, :segments
33
+
34
+ def initialize path_pattern, segments
35
+ @path_pattern = path_pattern
36
+ @segments = segments
37
+ end
38
+
39
+ ##
40
+ # All argument names from this pattern
41
+ # @return [Array<String>]
42
+ def arguments
43
+ @segments.select(&:provides_arguments?).map(&:arguments).flatten
44
+ end
45
+
46
+ ##
47
+ # Whether pattern contains a positional segment
48
+ # @return [Boolean]
49
+ def positional_segments?
50
+ @segments.any?(&:positional?)
51
+ end
52
+
53
+ ##
54
+ # Whether pattern contains a segment with a nontrivial resource pattern
55
+ # @return [Boolean]
56
+ def nontrivial_pattern_segments?
57
+ @segments.any?(&:nontrivial_resource_pattern?)
58
+ end
59
+
60
+ ##
61
+ # A template of this pattern - all resource id segments are
62
+ # stripped and replaced by '*'
63
+ # @return [String]
64
+ def template
65
+ @segments.map(&:pattern_template).join("/")
66
+ end
67
+
68
+ ##
69
+ # A parent template to this pattern or an empty string if a pattern
70
+ # can not have a parent (too short)
71
+ # @return [String]
72
+ def parent_template
73
+ return nil if segments.length <= 2
74
+ last_segment = segments.last
75
+ parent_pattern_segments = last_segment.provides_arguments? ? segments[0...-2] : segments[0...-1]
76
+ parent_pattern_segments.map(&:pattern_template).join("/")
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 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 PathPattern
19
+ ##
20
+ # A positional segment in a path pattern.
21
+ # positional segments have a pattern of wildcards and do not carry a name
22
+ #
23
+ # @!attribure [r] type
24
+ # @return [String] The type of this segment
25
+ # @!attribute [r] position
26
+ # @return [Integer] The argument position of this segment i.e.
27
+ # it's position if we remove all non-positional segments from the pattern
28
+ # @!attribute [r] pattern
29
+ # @return [String] The pattern of the segment, for the positional segment it is also
30
+ # a pattern of its resource
31
+ class PositionalSegment
32
+ attr_reader :type, :position, :pattern
33
+ def initialize position, pattern
34
+ @type = :positional
35
+ @position = position
36
+ @pattern = pattern
37
+ end
38
+
39
+ ##
40
+ # Whether the segment is positional
41
+ # @return [Boolean]
42
+ def positional?
43
+ true
44
+ end
45
+
46
+ ##
47
+ # Whether the segment provides a resource pattern
48
+ # @return [Boolean]
49
+ def resource_pattern?
50
+ true
51
+ end
52
+
53
+ ##
54
+ # Whether the segment provides a nontrivial resource pattern
55
+ # @return [Boolean]
56
+ def nontrivial_resource_pattern?
57
+ false
58
+ end
59
+
60
+ ##
61
+ # Whether the segment provides arguments
62
+ # @return [Boolean]
63
+ def provides_arguments?
64
+ true
65
+ end
66
+
67
+ ##
68
+ # Names of the segment's arguments
69
+ # @return [Array<String>]
70
+ def arguments
71
+ [position.to_s]
72
+ end
73
+
74
+ ##
75
+ # Returns a segment's pattern filled with dummy values
76
+ # names of the values are generated starting from the index provided
77
+ # @param start_index [Integer] a starting index for dummy value generation
78
+ # @return [String] a pattern filled with dummy values
79
+ def expected_path_for_dummy_values start_index
80
+ "value#{start_index}"
81
+ end
82
+
83
+ ##
84
+ # Path string for this segment
85
+ # @return [String]
86
+ def path_string
87
+ "\#{#{position}}"
88
+ end
89
+
90
+ ##
91
+ # A pattern template for this segment
92
+ # @return [String]
93
+ def pattern_template
94
+ pattern
95
+ end
96
+
97
+ # @private
98
+ def == other
99
+ return false unless other.is_a? self.class
100
+
101
+ (pattern == other.pattern && position == other.position)
102
+ end
103
+ end
104
+
105
+ # A ResourceId segment in a path pattern.
106
+ # ResourceId segments can be simple, with one resource name
107
+ # or complex, with multiple resource names divided by separators
108
+ #
109
+ # @!attribure [r] type
110
+ # @return [String] The type of this segment
111
+ # @!attribute [r] pattern
112
+ # @return [String] The pattern of the segment, for the positional segment it is also
113
+ # a pattern of its resource
114
+ # @!attribute [r] resource_names
115
+ # @return [Array<String>] The resource names in this segment
116
+ # @!attribute [r] resource_patterns
117
+ # @return [Array<String>] The resource patterns associated with
118
+ # the resource_names of this segment
119
+ class ResourceIdSegment
120
+ attr_reader :type, :pattern, :resource_names, :resource_patterns
121
+
122
+ def initialize type, pattern, resource_names, resource_patterns = []
123
+ @type = type
124
+ @pattern = pattern
125
+ @resource_names = resource_names
126
+ @resource_patterns = resource_patterns
127
+ end
128
+
129
+ ##
130
+ # Whether the segment is positional
131
+ # @return [Boolean]
132
+ def positional?
133
+ false
134
+ end
135
+
136
+ ##
137
+ # Whether the segment provides a resource pattern
138
+ # @return [Boolean]
139
+ def resource_pattern?
140
+ resource_patterns.any?
141
+ end
142
+
143
+ ##
144
+ # Whether the segment provides a nontrivial resource pattern
145
+ # @return [Boolean]
146
+ def nontrivial_resource_pattern?
147
+ resource_patterns.any? { |res_pattern| !res_pattern.match?(/^\*+$/) }
148
+ end
149
+
150
+ ##
151
+ # Whether the segment provides arguments
152
+ # @return [Boolean]
153
+ def provides_arguments?
154
+ true
155
+ end
156
+
157
+ ##
158
+ # Names of the segment's arguments
159
+ # @return [Array<String>]
160
+ def arguments
161
+ resource_names
162
+ end
163
+
164
+ ##
165
+ # Returns a segment's pattern filled with dummy values
166
+ # names of the values are generated starting from the index provided
167
+ # @param start_index [Integer] a starting index for dummy value generation
168
+ # @return [String] a pattern filled with dummy values
169
+ def expected_path_for_dummy_values start_index
170
+ return "value#{start_index}" if type == :simple_resource_id
171
+
172
+ resource_names.each_with_index.reduce pattern do |exp_path, (res_name, index)|
173
+ exp_path.sub "{#{res_name}}", "value#{start_index + index}"
174
+ end
175
+ end
176
+
177
+ ##
178
+ # Path string for this segment
179
+ # @return [String]
180
+ def path_string
181
+ type == :simple_resource_id ? "\#{#{resource_names[0]}}" : pattern.gsub("{", "\#{")
182
+ end
183
+
184
+ ##
185
+ # A pattern template for this segment
186
+ # @return [String]
187
+ def pattern_template
188
+ "*"
189
+ end
190
+
191
+ ##
192
+ # Initialization helper to create a simple resource without a pattern
193
+ # @param name [String] resource name
194
+ # @return [ResourceIdSegment]
195
+ def self.create_simple name
196
+ ResourceIdSegment.new :simple_resource_id, "{#{name}}", [name]
197
+ end
198
+
199
+ # @private
200
+ def == other
201
+ return false unless other.is_a? self.class
202
+
203
+ (type == other.type && pattern == other.pattern &&
204
+ resource_names == other.resource_names &&
205
+ resource_patterns == other.resource_patterns)
206
+ end
207
+ end
208
+
209
+ ##
210
+ # A CollectionId segment in a path template.
211
+ # CollectionId segments are basically string literals
212
+ #
213
+ # @!attribure [r] type
214
+ # @return [String] The type of this segment
215
+ # @!attribute [r] pattern
216
+ # @return [String] The pattern of the segment, for the positional segment it is also
217
+ # a pattern of its resource
218
+ class CollectionIdSegment
219
+ attr_reader :type, :pattern
220
+
221
+ def initialize pattern
222
+ @type = :collection_id
223
+ @pattern = pattern
224
+ end
225
+
226
+ ##
227
+ # Whether the segment is positional
228
+ # @return [Boolean]
229
+ def positional?
230
+ false
231
+ end
232
+
233
+ ##
234
+ # Whether the segment provides a resource pattern
235
+ # @return [Boolean]
236
+ def resource_pattern?
237
+ false
238
+ end
239
+
240
+ ##
241
+ # Whether the segment provides a nontrivial resource pattern
242
+ # @return [Boolean]
243
+ def nontrivial_resource_pattern?
244
+ false
245
+ end
246
+
247
+ ##
248
+ # Whether the segment provides arguments
249
+ # @return [Boolean]
250
+ def provides_arguments?
251
+ false
252
+ end
253
+
254
+ ##
255
+ # Path string for this segment
256
+ # @return [String]
257
+ def path_string
258
+ pattern
259
+ end
260
+
261
+ ##
262
+ # A pattern template for this segment
263
+ # @return [String]
264
+ def pattern_template
265
+ pattern
266
+ end
267
+
268
+ # @private
269
+ def == other
270
+ return false unless other.is_a? self.class
271
+
272
+ (pattern == other.pattern)
273
+ end
274
+ end
275
+ end
276
+ end
@@ -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?
@@ -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
 
@@ -194,8 +194,7 @@ module Gapic
194
194
  # @return [Array<String>] The segment key names.
195
195
  #
196
196
  def routing_params
197
- segments = Gapic::PathTemplate.parse method_path
198
- segments.select { |s| s.is_a? Gapic::PathTemplate::Segment }.map(&:name)
197
+ Gapic::UriTemplate.parse_arguments method_path
199
198
  end
200
199
 
201
200
  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
@@ -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
@@ -761,30 +762,32 @@ module Gapic
761
762
  # @return [Array<Gapic::Schema::ResourceDescriptor>] The resource
762
763
  # descriptor.
763
764
  # @!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
765
+ # @return [Array<String>] The template form of the
766
+ # patterns. Template means all ID segments are replaced by asterisks
766
767
  # to remove non-structural differences due to different names being
767
- # used. Segmented means simply split on slashes.
768
+ # used.
768
769
  # For example, if a pattern is `"projects/{project}""`, the
769
- # corresponding parsed pattern would be `["projects", "*"]`.
770
+ # corresponding parsed pattern would be `"projects/*"]`.
771
+ # @!attribure [r] parsed_parent_patterns
772
+ # return [Array<String>] Parsed patterns for the expected parents.
770
773
  # @!attribute [r] parent_resources
771
774
  # @return [Array<Gapic::Schema::Resource>] Parent resources
772
775
  class Resource
773
776
  extend Forwardable
774
- attr_reader :descriptor, :parsed_patterns, :parent_resources
777
+ attr_reader :descriptor, :parsed_patterns, :parsed_parent_patterns, :parent_resources
775
778
  attr_accessor :parent
776
779
 
777
780
  # Initializes a resource object.
778
- # @param descriptor [Google::Protobuf::ResourceDescriptor] the protobuf
781
+ # @param descriptor [Google::Api::ResourceDescriptor] the protobuf
779
782
  # representation of this resource.
780
783
  def initialize descriptor
781
784
  @parent = nil
782
785
  @descriptor = descriptor
783
- @parsed_patterns = descriptor.pattern.map do |pattern|
784
- pattern.split("/").map do |segment|
785
- segment =~ %r{\{[^/\}]+(=[^\}]+)?\}} ? "*" : segment
786
- end.freeze
786
+ patterns = descriptor.pattern.map do |pattern|
787
+ Gapic::PathPattern.parse pattern
787
788
  end.freeze
789
+ @parsed_patterns = patterns.map(&:template).compact.uniq.freeze
790
+ @parsed_parent_patterns = patterns.map(&:parent_template).compact.uniq.freeze
788
791
  @parent_resources = []
789
792
  end
790
793
 
@@ -800,15 +803,6 @@ module Gapic
800
803
  parent&.containing_file
801
804
  end
802
805
 
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
806
  # @!method type
813
807
  # @return [String] the resource type string.
814
808
  # @!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,7 @@
1
1
  <%- assert_locals pattern -%>
2
2
  The resource will be in the following format:
3
3
 
4
- `<%= pattern.template %>`
4
+ `<%= pattern.pattern %>`
5
5
 
6
6
  <%- pattern.arguments.each do |arg| -%>
7
7
  @param <%= arg %> [String]
@@ -1,7 +1,5 @@
1
1
  <%- assert_locals service -%>
2
- # frozen_string_literal: true
3
-
4
- <%= render partial: "shared/license" %>
2
+ <%= render partial: "shared/header" %>
5
3
  require "helper"
6
4
 
7
5
  require "gapic/grpc/service_stub"
@@ -1,7 +1,5 @@
1
1
  <%- assert_locals service -%>
2
- # frozen_string_literal: true
3
-
4
- <%= render partial: "shared/license" %>
2
+ <%= render partial: "shared/header" %>
5
3
  require "helper"
6
4
 
7
5
  require "gapic/grpc/service_stub"
@@ -1,7 +1,5 @@
1
1
  <%- assert_locals service -%>
2
- # frozen_string_literal: true
3
-
4
- <%= render partial: "shared/license" %>
2
+ <%= render partial: "shared/header" %>
5
3
  require "helper"
6
4
 
7
5
  require "gapic/grpc/service_stub"
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.6.0
4
+ version: 0.6.1
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-06-02 00:00:00.000000000 Z
13
+ date: 2020-06-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: actionpack
@@ -217,9 +217,10 @@ files:
217
217
  - lib/gapic/grpc_service_config/service_config.rb
218
218
  - lib/gapic/helpers/filepath_helper.rb
219
219
  - lib/gapic/helpers/namespace_helper.rb
220
- - lib/gapic/path_template.rb
221
- - lib/gapic/path_template/parser.rb
222
- - lib/gapic/path_template/segment.rb
220
+ - lib/gapic/path_pattern.rb
221
+ - lib/gapic/path_pattern/parser.rb
222
+ - lib/gapic/path_pattern/pattern.rb
223
+ - lib/gapic/path_pattern/segment.rb
223
224
  - lib/gapic/presenters.rb
224
225
  - lib/gapic/presenters/enum_presenter.rb
225
226
  - lib/gapic/presenters/enum_value_presenter.rb
@@ -239,6 +240,8 @@ files:
239
240
  - lib/gapic/schema/api.rb
240
241
  - lib/gapic/schema/loader.rb
241
242
  - lib/gapic/schema/wrappers.rb
243
+ - lib/gapic/uri_template.rb
244
+ - lib/gapic/uri_template/parser.rb
242
245
  - lib/google/api/annotations.pb.rb
243
246
  - lib/google/api/client.pb.rb
244
247
  - lib/google/api/field_behavior.pb.rb
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright 2019 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/path_template/segment"
18
-
19
- module Gapic
20
- module PathTemplate
21
- # A URI path template parser.
22
- #
23
- # @see https://tools.ietf.org/html/rfc6570 URI Template
24
- #
25
- # @!attribute [r] path_template
26
- # @return [String] The URI path template to be parsed.
27
- # @!attribute [r] segments
28
- # @return [Array<Segment|String>] The segments of the parsed URI path
29
- # template.
30
- class Parser
31
- # @private
32
- # /((?<positional>\*\*?)|{(?<name>[^\/]+?)(?:=(?<template>.+?))?})/
33
- PATH_TEMPLATE = %r{
34
- (
35
- (?<positional>\*\*?)
36
- |
37
- {(?<name>[^\/]+?)(?:=(?<template>.+?))?}
38
- )
39
- }x.freeze
40
-
41
- attr_reader :path_template, :segments
42
-
43
- # Create a new URI path template parser.
44
- #
45
- # @param path_template [String] The URI path template to be parsed.
46
- def initialize path_template
47
- @path_template = path_template
48
- @segments = parse! path_template
49
- end
50
-
51
- protected
52
-
53
- def parse! path_template
54
- # segments contain either Strings or segment objects
55
- segments = []
56
- segment_pos = 0
57
-
58
- while (match = PATH_TEMPLATE.match path_template)
59
- # The String before the match needs to be added to the segments
60
- segments << match.pre_match unless match.pre_match.empty?
61
-
62
- segment, segment_pos = segment_and_pos_from_match match, segment_pos
63
- segments << segment
64
-
65
- path_template = match.post_match
66
- end
67
-
68
- # Whatever String is unmatched needs to be added to the segments
69
- segments << path_template unless path_template.empty?
70
-
71
- segments
72
- end
73
-
74
- def segment_and_pos_from_match match, pos
75
- if match[:positional]
76
- [Segment.new(pos, match[:positional]), pos + 1]
77
- else
78
- [Segment.new(match[:name], match[:template]), pos]
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright 2019 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 PathTemplate
19
- # A segment in a URI path template.
20
- #
21
- # @see https://tools.ietf.org/html/rfc6570 URI Template
22
- #
23
- # @!attribute [r] name
24
- # @return [String, Integer] The name of a named segment, or the position
25
- # of a positional segment.
26
- # @!attribute [r] pattern
27
- # @return [String, nil] The pattern of the segment, nil if not set.
28
- class Segment
29
- attr_reader :name, :pattern
30
-
31
- def initialize name, pattern
32
- @name = name
33
- @pattern = pattern
34
- end
35
-
36
- # Determines if the segment is positional (has a number for a name).
37
- #
38
- # @return [Boolean]
39
- def positional?
40
- name.is_a? Integer
41
- end
42
-
43
- # Determines if the segment is named (has a string for a name).
44
- #
45
- # @return [Boolean]
46
- def named?
47
- !positional?
48
- end
49
-
50
- # Determines if the segment has a pattern. Positional segments always
51
- # have a pattern. Named segments may have a pattern if provided in the
52
- # URI path template.
53
- #
54
- # @return [Boolean]
55
- def pattern?
56
- !@pattern.nil?
57
- end
58
-
59
- # Determines if the segment has a nontrivial pattern (i.e. not `*` or `**`).
60
- #
61
- # @return [Boolean]
62
- def nontrivial_pattern?
63
- @pattern && @pattern != "*" && @pattern != "**"
64
- end
65
-
66
- # @private
67
- def == other
68
- return false unless other.is_a? self.class
69
-
70
- (name == other.name) && (pattern == other.pattern)
71
- end
72
- end
73
- end
74
- end