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 +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/gapic/file_formatter.rb +0 -1
- data/lib/gapic/generator/version.rb +1 -1
- data/lib/gapic/{path_template.rb → path_pattern.rb} +9 -8
- data/lib/gapic/path_pattern/parser.rb +146 -0
- data/lib/gapic/path_pattern/pattern.rb +80 -0
- data/lib/gapic/path_pattern/segment.rb +276 -0
- data/lib/gapic/presenters/gem_presenter.rb +11 -1
- data/lib/gapic/presenters/method_presenter.rb +2 -3
- data/lib/gapic/presenters/resource_presenter.rb +23 -31
- data/lib/gapic/schema/wrappers.rb +13 -19
- data/lib/gapic/uri_template.rb +36 -0
- data/lib/gapic/uri_template/parser.rb +50 -0
- data/templates/default/service/client/resource/_doc.erb +1 -1
- data/templates/default/service/test/client.erb +1 -3
- data/templates/default/service/test/client_operations.erb +1 -3
- data/templates/default/service/test/client_paths.erb +1 -3
- metadata +8 -5
- data/lib/gapic/path_template/parser.rb +0 -83
- data/lib/gapic/path_template/segment.rb +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b063888cabf4893087dcefa274cb8ab5a9469a762fc3dbb34af2e143cb1bcce4
|
4
|
+
data.tar.gz: 589dc9fdf67d63dc25fe62537783e6305e4441f51b5caa2c94a5b1a161e71ab7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07a03fd0adcc1640a37fa334883838aee76c124d2e5380a00d540751b3740e1b0f13d82a981ab35297c095df38620a0895bf4bb7bb5dbf1421c659e71cd92e85
|
7
|
+
data.tar.gz: 10269fc5c70542e1ae9ee1471eb6365c1669c741aa1ac03dbaf3b652cec2aee14801717589d1c45febc554b280cd8cd178ac19e02b1224b2692d1e98324142f6
|
data/CHANGELOG.md
CHANGED
@@ -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.
|
data/lib/gapic/file_formatter.rb
CHANGED
@@ -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/
|
17
|
+
require "gapic/path_pattern/parser"
|
18
18
|
|
19
19
|
module Gapic
|
20
20
|
# TODO: Enter docs
|
21
21
|
# Dooooooooocs!!!
|
22
|
-
module
|
23
|
-
# Parse a URI path
|
22
|
+
module PathPattern
|
23
|
+
# Parse a URI path pattern.
|
24
24
|
#
|
25
|
-
# @see https://
|
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
|
28
|
+
# @param path_pattern [String] The URI path template to be parsed.
|
28
29
|
#
|
29
|
-
# @return [
|
30
|
+
# @return [PathPattern::Pattern] The parsed pattern
|
30
31
|
# path template.
|
31
|
-
def self.parse
|
32
|
-
Parser.
|
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/
|
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
|
-
|
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/
|
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 { |
|
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
|
57
|
-
@
|
58
|
-
@
|
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 :
|
62
|
+
attr_reader :pattern, :path_string
|
64
63
|
|
65
64
|
def useful_for_helpers?
|
66
|
-
|
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 { |
|
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 { |
|
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 =
|
83
|
-
segments.map do |segment|
|
84
|
-
if segment.
|
85
|
-
|
86
|
-
|
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
|
-
|
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
|
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<
|
765
|
-
# patterns.
|
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.
|
768
|
+
# used.
|
768
769
|
# For example, if a pattern is `"projects/{project}""`, the
|
769
|
-
# corresponding parsed pattern would be `
|
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::
|
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
|
-
|
784
|
-
|
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
|
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.
|
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-
|
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/
|
221
|
-
- lib/gapic/
|
222
|
-
- lib/gapic/
|
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
|