gapic-generator 0.4.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 +31 -0
- data/lib/gapic/file_formatter.rb +0 -1
- data/lib/gapic/formatting_utils.rb +6 -6
- data/lib/gapic/generator/version.rb +1 -1
- data/lib/gapic/generators/default_generator.rb +16 -14
- data/lib/gapic/helpers/filepath_helper.rb +1 -0
- data/lib/gapic/helpers/namespace_helper.rb +8 -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/field_presenter.rb +9 -9
- data/lib/gapic/presenters/file_presenter.rb +1 -1
- data/lib/gapic/presenters/gem_presenter.rb +39 -3
- data/lib/gapic/presenters/method_presenter.rb +19 -19
- data/lib/gapic/presenters/package_presenter.rb +4 -3
- data/lib/gapic/presenters/resource_presenter.rb +48 -36
- data/lib/gapic/presenters/service_presenter.rb +20 -14
- data/lib/gapic/schema/api.rb +7 -0
- 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/gem/gemfile.erb +3 -0
- data/templates/default/gem/gemspec.erb +7 -6
- data/templates/default/gem/rakefile.erb +1 -0
- data/templates/default/gem/test_helper.erb +8 -0
- data/templates/default/layouts/_ruby.erb +5 -4
- data/templates/default/lib/_service.erb +2 -0
- data/templates/default/proto_docs/_message.erb +2 -2
- data/templates/default/service/client/_client.erb +7 -4
- data/templates/default/service/client/_config.erb +33 -29
- data/templates/default/service/client/_credentials.erb +1 -1
- data/templates/default/service/client/_operations.erb +3 -1
- data/templates/default/service/client/method/def/_options_defaults.erb +2 -2
- data/templates/default/service/client/method/def/_request_normal.erb +2 -2
- data/templates/default/service/client/method/def/_request_streaming.erb +3 -3
- data/templates/default/service/client/method/def/_response_normal.erb +1 -1
- data/templates/default/service/client/method/def/_response_paged.erb +2 -2
- data/templates/default/service/client/method/docs/_error.erb +1 -1
- data/templates/default/service/client/method/docs/_request_normal.erb +2 -2
- data/templates/default/service/client/method/docs/_request_streaming.erb +2 -2
- data/templates/default/service/client/method/docs/_response.erb +1 -1
- data/templates/default/service/client/resource/_def.erb +1 -1
- data/templates/default/service/client/resource/_doc.erb +1 -1
- data/templates/default/service/client/resource/_multi.erb +4 -7
- data/templates/default/service/client/resource/_single.erb +2 -3
- data/templates/default/service/test/_resource.erb +16 -0
- data/templates/default/service/test/client.erb +2 -5
- data/templates/default/service/test/client_operations.erb +2 -5
- data/templates/default/service/test/client_paths.erb +15 -0
- metadata +12 -6
- data/lib/gapic/path_template/parser.rb +0 -83
- data/lib/gapic/path_template/segment.rb +0 -67
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,36 @@
|
|
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
|
+
|
9
|
+
### 0.6.0 / 2020-06-02
|
10
|
+
|
11
|
+
* Support for clients with generic endpoint and credentials.
|
12
|
+
* Support for adding extra dependencies.
|
13
|
+
* Fixed a Ruby warning when looking up RPC-scoped configs with no parent.
|
14
|
+
* Internal: Presenters reference their parent rather than creating new objects.
|
15
|
+
|
16
|
+
### 0.5.1 / 2020-05-21
|
17
|
+
|
18
|
+
* Support a configuration for overriding service module names.
|
19
|
+
* Operations client honors the quota_project setting.
|
20
|
+
|
21
|
+
### 0.5.0 / 2020-05-19
|
22
|
+
|
23
|
+
* Add quota_project to the generated configs.
|
24
|
+
* Allow resource patterns with a star as a segment template.
|
25
|
+
* Generate tests for resource path helpers.
|
26
|
+
* Pin protobuf dependency for Ruby < 2.5.
|
27
|
+
* Create a test helper in for generated tests.
|
28
|
+
|
29
|
+
### 0.4.2 / 2020-04-28
|
30
|
+
|
31
|
+
* Prepend double-colon to absolute/global namespaces to prevent conflicts.
|
32
|
+
* Fix documentation/examples of timeouts to clarify they are in seconds.
|
33
|
+
|
3
34
|
### 0.4.0 / 2020-04-20
|
4
35
|
|
5
36
|
* Support generating clients of "common" interfaces by delegating to another service config.
|
data/lib/gapic/file_formatter.rb
CHANGED
@@ -137,15 +137,15 @@ module Gapic
|
|
137
137
|
|
138
138
|
case entity
|
139
139
|
when Gapic::Schema::Service
|
140
|
-
"{
|
140
|
+
"{::#{convert_address_to_ruby entity}::Client #{text}}"
|
141
141
|
when Gapic::Schema::Method
|
142
|
-
"{
|
142
|
+
"{::#{convert_address_to_ruby entity.parent}::Client##{entity.name.underscore} #{text}}"
|
143
143
|
when Gapic::Schema::Message, Gapic::Schema::Enum
|
144
|
-
"{
|
144
|
+
"{::#{convert_address_to_ruby entity} #{text}}"
|
145
145
|
when Gapic::Schema::EnumValue
|
146
|
-
"{
|
146
|
+
"{::#{convert_address_to_ruby entity.parent}::#{entity.name} #{text}}"
|
147
147
|
when Gapic::Schema::Field
|
148
|
-
"{
|
148
|
+
"{::#{convert_address_to_ruby entity.parent}##{entity.name} #{text}}"
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
@@ -155,7 +155,7 @@ module Gapic
|
|
155
155
|
address = entity.address
|
156
156
|
address = address.join "." if address.is_a? Array
|
157
157
|
address = address.sub file.package, file.ruby_package if file.ruby_package&.present?
|
158
|
-
address.split(
|
158
|
+
address.split(/\.|::/).reject(&:empty?).map(&:camelize).map { |node| api.fix_namespace node }.join("::")
|
159
159
|
end
|
160
160
|
end
|
161
161
|
end
|
@@ -41,10 +41,10 @@ module Gapic
|
|
41
41
|
# @return [Array<
|
42
42
|
# Google::Protobuf::Compiler::CodeGeneratorResponse::File>]
|
43
43
|
# The files that were generated for the API.
|
44
|
-
def generate
|
44
|
+
def generate gem_presenter: nil
|
45
45
|
files = []
|
46
46
|
|
47
|
-
gem = Gapic::Presenters.gem_presenter
|
47
|
+
gem = gem_presenter || Gapic::Presenters.gem_presenter(@api)
|
48
48
|
|
49
49
|
gem.packages.each do |package|
|
50
50
|
# Package level files
|
@@ -54,26 +54,28 @@ module Gapic
|
|
54
54
|
# Service level files
|
55
55
|
files << g("service.erb", "lib/#{service.service_file_path}", service: service)
|
56
56
|
files << g("service/client.erb", "lib/#{service.client_file_path}", service: service)
|
57
|
-
files << g("service/credentials.erb", "lib/#{service.credentials_file_path}", service: service)
|
57
|
+
files << g("service/credentials.erb", "lib/#{service.credentials_file_path}", service: service) unless gem.generic_endpoint?
|
58
58
|
files << g("service/paths.erb", "lib/#{service.paths_file_path}", service: service) if service.paths?
|
59
59
|
files << g("service/operations.erb", "lib/#{service.operations_file_path}", service: service) if service.lro?
|
60
60
|
files << g("service/test/client.erb", "test/#{service.test_client_file_path}", service: service)
|
61
|
+
files << g("service/test/client_paths.erb", "test/#{service.test_paths_file_path}", service: service) if service.paths?
|
61
62
|
files << g("service/test/client_operations.erb", "test/#{service.test_client_operations_file_path}", service: service) if service.lro?
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
65
66
|
# Gem level files
|
66
|
-
files << g("gem/gitignore.erb",
|
67
|
-
files << g("gem/version.erb",
|
68
|
-
files << g("gem/
|
69
|
-
files << g("gem/
|
70
|
-
files << g("gem/
|
71
|
-
files << g("gem/
|
72
|
-
files << g("gem/
|
73
|
-
files << g("gem/
|
74
|
-
files << g("gem/
|
75
|
-
files << g("gem/
|
76
|
-
files << g("gem/
|
67
|
+
files << g("gem/gitignore.erb", ".gitignore", gem: gem)
|
68
|
+
files << g("gem/version.erb", "lib/#{gem.version_file_path}", gem: gem)
|
69
|
+
files << g("gem/test_helper.erb", "test/helper.rb", gem: gem)
|
70
|
+
files << g("gem/gemspec.erb", "#{gem.name}.gemspec", gem: gem)
|
71
|
+
files << g("gem/gemfile.erb", "Gemfile", gem: gem)
|
72
|
+
files << g("gem/rakefile.erb", "Rakefile", gem: gem)
|
73
|
+
files << g("gem/readme.erb", "README.md", gem: gem)
|
74
|
+
files << g("gem/changelog.erb", "CHANGELOG.md", gem: gem)
|
75
|
+
files << g("gem/rubocop.erb", ".rubocop.yml", gem: gem)
|
76
|
+
files << g("gem/yardopts.erb", ".yardopts", gem: gem)
|
77
|
+
files << g("gem/license.erb", "LICENSE.md", gem: gem)
|
78
|
+
files << g("gem/entrypoint.erb", "lib/#{gem.name}.rb", gem: gem)
|
77
79
|
|
78
80
|
gem.proto_files.each do |proto_file|
|
79
81
|
files << g("proto_docs/proto_file.erb", "proto_docs/#{proto_file.docs_file_path}", file: proto_file)
|
@@ -38,7 +38,14 @@ module Gapic
|
|
38
38
|
# Ruby double-semicolon separators.
|
39
39
|
def ruby_namespace_for_address address
|
40
40
|
address = address.split "." if address.is_a? String
|
41
|
-
address.reject(&:empty?).map(&:camelize).join
|
41
|
+
ensure_absolute_namespace address.reject(&:empty?).map(&:camelize).join("::")
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Returns the given namespace, ensuring double colons are prepended
|
46
|
+
#
|
47
|
+
def ensure_absolute_namespace namespace
|
48
|
+
namespace.start_with?("::") ? namespace : "::#{namespace}"
|
42
49
|
end
|
43
50
|
|
44
51
|
##
|
@@ -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
|