gapic-generator 0.3.1 → 0.5.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/lib/gapic/formatting_utils.rb +9 -7
  4. data/lib/gapic/generator/version.rb +1 -1
  5. data/lib/gapic/generators/default_generator.rb +13 -11
  6. data/lib/gapic/helpers/filepath_helper.rb +1 -0
  7. data/lib/gapic/helpers/namespace_helper.rb +8 -1
  8. data/lib/gapic/path_template/segment.rb +7 -0
  9. data/lib/gapic/presenters/field_presenter.rb +9 -9
  10. data/lib/gapic/presenters/file_presenter.rb +1 -1
  11. data/lib/gapic/presenters/method_presenter.rb +23 -17
  12. data/lib/gapic/presenters/package_presenter.rb +8 -1
  13. data/lib/gapic/presenters/resource_presenter.rb +55 -35
  14. data/lib/gapic/presenters/service_presenter.rb +56 -19
  15. data/lib/gapic/ruby_info.rb +93 -0
  16. data/lib/gapic/schema/api.rb +63 -1
  17. data/templates/default/gem/gemfile.erb +3 -0
  18. data/templates/default/gem/gemspec.erb +3 -1
  19. data/templates/default/gem/rakefile.erb +1 -0
  20. data/templates/default/gem/test_helper.erb +8 -0
  21. data/templates/default/layouts/_ruby.erb +5 -4
  22. data/templates/default/proto_docs/_message.erb +2 -2
  23. data/templates/default/service/client.erb +1 -1
  24. data/templates/default/service/client/_client.erb +15 -4
  25. data/templates/default/service/client/_config.erb +32 -28
  26. data/templates/default/service/client/_credentials.erb +1 -1
  27. data/templates/default/service/client/_operations.erb +3 -1
  28. data/templates/default/service/client/method/def/_options_defaults.erb +2 -2
  29. data/templates/default/service/client/method/def/_request_normal.erb +2 -2
  30. data/templates/default/service/client/method/def/_request_streaming.erb +3 -3
  31. data/templates/default/service/client/method/def/_response_normal.erb +1 -1
  32. data/templates/default/service/client/method/def/_response_paged.erb +2 -2
  33. data/templates/default/service/client/method/docs/_error.erb +1 -1
  34. data/templates/default/service/client/method/docs/_request_normal.erb +2 -2
  35. data/templates/default/service/client/method/docs/_request_streaming.erb +2 -2
  36. data/templates/default/service/client/method/docs/_response.erb +1 -1
  37. data/templates/default/service/client/resource/_def.erb +1 -1
  38. data/templates/default/service/client/resource/_multi.erb +4 -7
  39. data/templates/default/service/client/resource/_single.erb +2 -3
  40. data/templates/default/service/credentials.erb +1 -1
  41. data/templates/default/service/operations.erb +1 -1
  42. data/templates/default/service/paths.erb +1 -1
  43. data/templates/default/service/test/_resource.erb +16 -0
  44. data/templates/default/service/test/client.erb +17 -4
  45. data/templates/default/service/test/client_operations.erb +3 -4
  46. data/templates/default/service/test/client_paths.erb +17 -0
  47. data/templates/default/service/test/method/_configure.erb +19 -0
  48. metadata +8 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c03115844b852a0a3434c5f17fa3140e49c9c2eccefd12f66bc7613c5117ea35
4
- data.tar.gz: 265ca6503985d740d36bc4d0660c14d37f877d3362f181b56bed1d5ddd1ffb2f
3
+ metadata.gz: 3aaec7f146400572f3b4ad346c8a69849ff3903073eadabd7eec6f6e882d6bb9
4
+ data.tar.gz: 39987ab08fe97c6e4acdcfe3357e398df99db73f2ab95960c8c1015456f79224
5
5
  SHA512:
6
- metadata.gz: a8319b1bd6e1ac17ab22b365e97056b09d4f7537390e4689dca4f58d3d1587ef749ed95f0bd457bc2d30943a8b418204a416743003fb4e5339a983cb839673f4
7
- data.tar.gz: 8b3bfae44552ee39a3f642aa9703dbc6a9eebe01174dfff0e20a9c0aecd69c3ddfb0ec669f62a63b51d275fd458ed4e65948bc3a434a15ed18b14316b3f2ff12
6
+ metadata.gz: 87bfd8d75d938d8e82ff4fc5b17aab92260dedb745faf47c5abda914920145d85a0415c43ddc57126bd7942fe1b76801ed53d4a2d0b14f851adb3539ce34d0c6
7
+ data.tar.gz: 89e9820c8f7ba98c77165e3ff0fb38ae2b84b333873bf458ca7c87dca1e0a38c7a09f5940027fe081a2589ef429488ebd7bad94284bc343b918faf414486296b
@@ -1,5 +1,40 @@
1
1
  # Release History for gapic-generator
2
2
 
3
+ ### 0.5.1 / 2020-05-21
4
+
5
+ * Support a configuration for overriding service module names.
6
+ * Operations client honors the quota_project setting.
7
+
8
+ ### 0.5.0 / 2020-05-19
9
+
10
+ * Add quota_project to the generated configs.
11
+ * Allow resource patterns with a star as a segment template.
12
+ * Generate tests for resource path helpers.
13
+ * Pin protobuf dependency for Ruby < 2.5.
14
+ * Create a test helper in for generated tests.
15
+
16
+ ### 0.4.2 / 2020-04-28
17
+
18
+ * Prepend double-colon to absolute/global namespaces to prevent conflicts.
19
+ * Fix documentation/examples of timeouts to clarify they are in seconds.
20
+
21
+ ### 0.4.0 / 2020-04-20
22
+
23
+ * Support generating clients of "common" interfaces by delegating to another service config.
24
+ * Added an accessor for the long-running-operation client from the main client.
25
+ * Generate tests for the configure method and operations client accessor.
26
+ * Prevent generation of RPC or factory methods with reserved names.
27
+ * Fixed: LRO clients weren't inheriting custom endpoints from the main client.
28
+ * Fixed: Cross-references weren't interpreted if the text included backticks, spaces, or hyphens.
29
+
30
+ ### 0.3.3 / 2020-04-13
31
+
32
+ * Fix cross-reference links to multi-word enum values.
33
+
34
+ ### 0.3.2 / 2020-04-12
35
+
36
+ * Fix the talent.v4beta1 hack.
37
+
3
38
  ### 0.3.1 / 2020-04-11
4
39
 
5
40
  * Disable ModuleLength metric for generated code.
@@ -22,7 +22,7 @@ module Gapic
22
22
  #
23
23
  module FormattingUtils
24
24
  @brace_detector = /\A(?<pre>[^`]*(`[^`]*`[^`]*)*[^`\\])?\{(?<inside>[^\s][^}]*)\}(?<post>.*)\z/m
25
- @xref_detector = /\A(?<pre>[^`]*(`[^`]*`[^`]*)*)?\[(?<text>[\w\.]+)\]\[(?<addr>[\w\.]+)\](?<post>.*)\z/m
25
+ @xref_detector = /\A(?<pre>[^`]*(`[^`]*`[^`]*)*)?\[(?<text>[\w\. `-]+)\]\[(?<addr>[\w\.]+)\](?<post>.*)\z/m
26
26
  @list_element_detector = /\A\s*(\*|\+|-|[0-9a-zA-Z]+\.)\s/
27
27
 
28
28
  class << self
@@ -137,13 +137,15 @@ module Gapic
137
137
 
138
138
  case entity
139
139
  when Gapic::Schema::Service
140
- "{#{convert_address_to_ruby entity}::Client #{text}}"
140
+ "{::#{convert_address_to_ruby entity}::Client #{text}}"
141
141
  when Gapic::Schema::Method
142
- "{#{convert_address_to_ruby entity.parent}::Client##{entity.name.underscore} #{text}}"
143
- when Gapic::Schema::Message, Gapic::Schema::Enum, Gapic::Schema::EnumValue
144
- "{#{convert_address_to_ruby entity} #{text}}"
142
+ "{::#{convert_address_to_ruby entity.parent}::Client##{entity.name.underscore} #{text}}"
143
+ when Gapic::Schema::Message, Gapic::Schema::Enum
144
+ "{::#{convert_address_to_ruby entity} #{text}}"
145
+ when Gapic::Schema::EnumValue
146
+ "{::#{convert_address_to_ruby entity.parent}::#{entity.name} #{text}}"
145
147
  when Gapic::Schema::Field
146
- "{#{convert_address_to_ruby entity.parent}##{entity.name} #{text}}"
148
+ "{::#{convert_address_to_ruby entity.parent}##{entity.name} #{text}}"
147
149
  end
148
150
  end
149
151
 
@@ -153,7 +155,7 @@ module Gapic
153
155
  address = entity.address
154
156
  address = address.join "." if address.is_a? Array
155
157
  address = address.sub file.package, file.ruby_package if file.ruby_package&.present?
156
- address.split(".").reject(&:empty?).map(&:camelize).map { |node| api.fix_namespace node }.join("::")
158
+ address.split(/\.|::/).reject(&:empty?).map(&:camelize).map { |node| api.fix_namespace node }.join("::")
157
159
  end
158
160
  end
159
161
  end
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Gapic
18
18
  module Generator
19
- VERSION = "0.3.1"
19
+ VERSION = "0.5.1"
20
20
  end
21
21
  end
@@ -58,22 +58,24 @@ module Gapic
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", ".gitignore", gem: gem)
67
- files << g("gem/version.erb", "lib/#{gem.version_file_path}", gem: gem)
68
- files << g("gem/gemspec.erb", "#{gem.name}.gemspec", gem: gem)
69
- files << g("gem/gemfile.erb", "Gemfile", gem: gem)
70
- files << g("gem/rakefile.erb", "Rakefile", gem: gem)
71
- files << g("gem/readme.erb", "README.md", gem: gem)
72
- files << g("gem/changelog.erb", "CHANGELOG.md", gem: gem)
73
- files << g("gem/rubocop.erb", ".rubocop.yml", gem: gem)
74
- files << g("gem/yardopts.erb", ".yardopts", gem: gem)
75
- files << g("gem/license.erb", "LICENSE.md", gem: gem)
76
- files << g("gem/entrypoint.erb", "lib/#{gem.name}.rb", gem: 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)
@@ -25,6 +25,7 @@ module Gapic
25
25
  ##
26
26
  # Converts a ruby namespace string to a file path string.
27
27
  def ruby_file_path api, namespace
28
+ namespace = namespace.sub(/^::/, "")
28
29
  file_path = ruby_file_path_for_namespace namespace
29
30
  fix_file_path api, file_path
30
31
  end
@@ -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
  ##
@@ -56,6 +56,13 @@ module Gapic
56
56
  !@pattern.nil?
57
57
  end
58
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
+
59
66
  # @private
60
67
  def == other
61
68
  return false unless other.is_a? self.class
@@ -95,21 +95,21 @@ module Gapic
95
95
  base_type =
96
96
  if field.message?
97
97
  type = message_ruby_type field.message
98
- output ? type : "#{type}, Hash"
98
+ output ? type : "#{type}, ::Hash"
99
99
  elsif field.enum?
100
100
  # TODO: handle when arg message is nil and enum is the type
101
101
  message_ruby_type field.enum
102
102
  else
103
103
  case field.type
104
- when 1, 2 then "Float"
105
- when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "Integer"
106
- when 9, 12 then "String"
107
- when 8 then "Boolean"
104
+ when 1, 2 then "::Float"
105
+ when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "::Integer"
106
+ when 9, 12 then "::String"
107
+ when 8 then "::Boolean"
108
108
  else
109
- "Object"
109
+ "::Object"
110
110
  end
111
111
  end
112
- field.repeated? ? "Array<#{base_type}>" : base_type
112
+ field.repeated? ? "::Array<#{base_type}>" : base_type
113
113
  end
114
114
 
115
115
  def field_map_type entry_message, output
@@ -118,7 +118,7 @@ module Gapic
118
118
  key_field = field if field.name == "key"
119
119
  value_field = field if field.name == "value"
120
120
  end
121
- class_name = output ? "Google::Protobuf::Map" : "Hash"
121
+ class_name = output ? "::Google::Protobuf::Map" : "::Hash"
122
122
  if key_field && value_field
123
123
  key_type = field_doc_types key_field, output
124
124
  value_type = field_doc_types value_field, output
@@ -141,7 +141,7 @@ module Gapic
141
141
  when 9, 12 then "\"hello world\""
142
142
  when 8 then "true"
143
143
  else
144
- "Object"
144
+ "::Object"
145
145
  end
146
146
  end
147
147
  end
@@ -39,7 +39,7 @@ module Gapic
39
39
  end
40
40
 
41
41
  def namespace
42
- return @file.ruby_package if @file.ruby_package.present?
42
+ return ensure_absolute_namespace @file.ruby_package if @file.ruby_package.present?
43
43
  ruby_namespace_for_address address
44
44
  end
45
45
 
@@ -16,6 +16,7 @@
16
16
 
17
17
  require "active_support/inflector"
18
18
  require "gapic/path_template"
19
+ require "gapic/ruby_info"
19
20
  require "gapic/helpers/namespace_helper"
20
21
 
21
22
  module Gapic
@@ -36,7 +37,11 @@ module Gapic
36
37
  end
37
38
 
38
39
  def name
39
- ActiveSupport::Inflector.underscore @method.name
40
+ @name ||= begin
41
+ candidate = ActiveSupport::Inflector.underscore @method.name
42
+ candidate = "call_#{candidate}" if Gapic::RubyInfo.excluded_method_names.include? candidate
43
+ candidate
44
+ end
40
45
  end
41
46
 
42
47
  def kind
@@ -59,13 +64,13 @@ module Gapic
59
64
 
60
65
  def doc_response_type
61
66
  ret = return_type
62
- ret = "Gapic::Operation" if lro?
67
+ ret = "::Gapic::Operation" if lro?
63
68
  if server_streaming?
64
- ret = "Enumerable<#{ret}>"
69
+ ret = "::Enumerable<#{ret}>"
65
70
  elsif paged?
66
71
  paged_type = paged_response_type
67
- paged_type = "Gapic::Operation" if paged_type == "Google::Longrunning::Operation"
68
- ret = "Gapic::PagedEnumerable<#{paged_type}>"
72
+ paged_type = "::Gapic::Operation" if paged_type == "::Google::Longrunning::Operation"
73
+ ret = "::Gapic::PagedEnumerable<#{paged_type}>"
69
74
  end
70
75
  ret
71
76
  end
@@ -118,7 +123,7 @@ module Gapic
118
123
  return [
119
124
  OpenStruct.new(
120
125
  name: "operation",
121
- doc_types: "Gapic::Operation"
126
+ doc_types: "::Gapic::Operation"
122
127
  )
123
128
  ]
124
129
  end
@@ -129,7 +134,7 @@ module Gapic
129
134
  ),
130
135
  OpenStruct.new(
131
136
  name: "operation",
132
- doc_types: "GRPC::ActiveCall::Operation"
137
+ doc_types: "::GRPC::ActiveCall::Operation"
133
138
  )
134
139
  ]
135
140
  end
@@ -145,9 +150,9 @@ module Gapic
145
150
  end
146
151
 
147
152
  def lro?
148
- return paged_response_type == "Google::Longrunning::Operation" if paged?
153
+ return paged_response_type == "::Google::Longrunning::Operation" if paged?
149
154
 
150
- message_ruby_type(@method.output) == "Google::Longrunning::Operation"
155
+ message_ruby_type(@method.output) == "::Google::Longrunning::Operation"
151
156
  end
152
157
 
153
158
  def client_streaming?
@@ -166,8 +171,9 @@ module Gapic
166
171
  # to be removed when these methods no longer conform to AIP-4233.) For
167
172
  # detailed information, see internal link go/actools-talent-pagination.
168
173
  address = @method.address.join "."
169
- return false if address == "google.cloud.talent.v4beta1.SearchProfiles"
170
- return false if address == "google.cloud.talent.v4beta1.SearchJobs"
174
+ return false if address == "google.cloud.talent.v4beta1.ProfileService.SearchProfiles"
175
+ return false if address == "google.cloud.talent.v4beta1.JobService.SearchJobs"
176
+ return false if address == "google.cloud.talent.v4beta1.JobService.SearchJobsForAlert"
171
177
 
172
178
  paged_request?(@method.input) && paged_response?(@method.output)
173
179
  end
@@ -220,12 +226,12 @@ module Gapic
220
226
  message_ruby_type arg.enum
221
227
  else
222
228
  case arg.type
223
- when 1, 2 then "Float"
224
- when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "Integer"
225
- when 9, 12 then "String"
226
- when 8 then "Boolean"
229
+ when 1, 2 then "::Float"
230
+ when 3, 4, 5, 6, 7, 13, 15, 16, 17, 18 then "::Integer"
231
+ when 9, 12 then "::String"
232
+ when 8 then "::Boolean"
227
233
  else
228
- "Object"
234
+ "::Object"
229
235
  end
230
236
  end
231
237
  end
@@ -250,7 +256,7 @@ module Gapic
250
256
  when 9, 12 then "\"hello world\""
251
257
  when 8 then "true"
252
258
  else
253
- "Object"
259
+ "::Object"
254
260
  end
255
261
  end
256
262
  end
@@ -53,10 +53,17 @@ module Gapic
53
53
  namespace.split("::").last
54
54
  end
55
55
 
56
+ # Services whose clients should be generated in this package namespace.
56
57
  def services
57
58
  @services ||= begin
58
59
  files = @api.generate_files.select { |f| f.package == @package }
59
- files.map(&:services).flatten.map { |s| ServicePresenter.new @api, s }
60
+ services = files.map(&:services).flatten
61
+ # Omit common services in this package. Common service clients do not
62
+ # go into their own package.
63
+ normal_services = services.select { |s| @api.delegate_service_for(s).nil? }
64
+ # But include common services that delegate to normal services in this package.
65
+ common_services = normal_services.flat_map { |s| @api.common_services_for s }
66
+ (normal_services + common_services).map { |s| ServicePresenter.new @api, s }
60
67
  end
61
68
  end
62
69
 
@@ -15,7 +15,6 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require "gapic/path_template"
18
- require "ostruct"
19
18
  require "active_support/inflector"
20
19
 
21
20
  module Gapic
@@ -28,20 +27,10 @@ module Gapic
28
27
  def initialize resource
29
28
  @resource = resource
30
29
 
31
- @patterns = resource.pattern.map do |template|
32
- segments = Gapic::PathTemplate.parse template
33
- OpenStruct.new(
34
- template: template,
35
- segments: segments,
36
- arguments: arguments_for(segments),
37
- path_string: path_string_for(segments)
38
- )
39
- end
30
+ @patterns = resource.pattern.map { |template| PatternPresenter.new template }
40
31
 
41
32
  # Keep only patterns that can be used to create path helpers
42
- @patterns.reject! do |pattern|
43
- named_arg_patterns?(pattern.segments) || positional_args?(pattern.segments)
44
- end
33
+ @patterns.filter!(&:useful_for_helpers?)
45
34
  end
46
35
 
47
36
  def name
@@ -60,33 +49,64 @@ module Gapic
60
49
  "#{ActiveSupport::Inflector.underscore name}_path"
61
50
  end
62
51
 
63
- private
52
+ ##
53
+ # A presenter for a particular pattern
54
+ #
55
+ class PatternPresenter
56
+ def initialize template
57
+ @template = template
58
+ @segments = Gapic::PathTemplate.parse template
59
+ @arguments = arg_segments.map(&:name)
60
+ @path_string = build_path_string
61
+ end
64
62
 
65
- def arguments_for segments
66
- arg_segments(segments).map(&:name)
67
- end
63
+ attr_reader :template, :segments, :arguments, :path_string
68
64
 
69
- def arg_segments segments
70
- segments.select { |segment| segment.is_a? Gapic::PathTemplate::Segment }
71
- end
65
+ def useful_for_helpers?
66
+ arg_segments.none?(&:nontrivial_pattern?) && arg_segments.none?(&:positional?)
67
+ end
72
68
 
73
- def path_string_for segments
74
- segments.map do |segment|
75
- if segment.is_a? Gapic::PathTemplate::Segment
76
- "\#{#{segment.name}}"
77
- else
78
- # Should be a String
79
- segment
80
- end
81
- end.join
82
- end
69
+ def formal_arguments
70
+ arguments.map { |arg| "#{arg}:" }.join ", "
71
+ end
83
72
 
84
- def positional_args? segments
85
- arg_segments(segments).any?(&:positional?)
86
- end
73
+ def arguments_key
74
+ arguments.sort.join ":"
75
+ end
76
+
77
+ def arguments_with_dummy_values
78
+ arguments.each_with_index.map { |arg, index| "#{arg}: \"value#{index}\"" }.join ", "
79
+ end
80
+
81
+ 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}"
87
+ else
88
+ # Should be a String
89
+ segment
90
+ end
91
+ end.join
92
+ end
87
93
 
88
- def named_arg_patterns? segments
89
- arg_segments(segments).any?(&:pattern)
94
+ private
95
+
96
+ def arg_segments
97
+ segments.select { |segment| segment.is_a? Gapic::PathTemplate::Segment }
98
+ end
99
+
100
+ 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
109
+ end
90
110
  end
91
111
  end
92
112
  end