gapic-generator 0.6.5 → 0.6.10

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: 27e2894595efed8561aa48e9059465257267e7f29310a806251bcc6d4d85c63f
4
- data.tar.gz: af47f16264074317a8d02e73539208a4b43f565ae346aef480619bc73a6b1203
3
+ metadata.gz: 4fd38043485e7ffbb2e8edf375019429972c5ac01b8be85803c5f6f9518b06c5
4
+ data.tar.gz: 23312fda7203a549f3e2f714df2ef73a0d71aea1aae369104de8ba079d4746c1
5
5
  SHA512:
6
- metadata.gz: eacd1840fadb1236cb5ed7efe7ba254a977529435ee7ddff1fcee7bb900fa847ccc0a3b861098f1292a63f72e82f6065146f1f0a0260b0624dc9a184de3d3389
7
- data.tar.gz: 8a93aaef7317b85fc048604b626af4cef13cf90ea2dd785a12180d94d71dbf0bc4ea24a34c828a04825adcfd4ae2b88e4cc3934d41de7de01b3be27f6302aaba
6
+ metadata.gz: cef8f93df7ca8b3207815a9c8239eeea6fb783265943d6ec22b246945582df439ddad1419a1783df8c0c1a3e432194a8ddb204c08856ac67dce5abb030ede394
7
+ data.tar.gz: 82df4fc573990154f629711aa9829d0c8aa6aacb2df34bcff9cff140dd5049de1f135325c5df089ca9b6b9188fae415e1bad351df8e6904bc1e071c0ae3ee63b
@@ -1,5 +1,29 @@
1
1
  # Release History for gapic-generator
2
2
 
3
+ ### 0.6.10 / 2021-01-13
4
+
5
+ * A set of human-readable command-line parameters can now be specified for the gapic-generator, e.g. `gem-name`. These parameters strictly duplicate the existing behaviour of old command-line parameters, e.g. `:gem.:name`.
6
+ * Documentation for the `timeout` parameter in some templates has been fixed to correctly specify 'seconds' where previously it incorrectly sais 'milliseconds'. This is a purely documentation update, no functionality changes.
7
+
8
+ ### 0.6.9 / 2020-12-07
9
+
10
+ * Load package-level handwritten helpers.
11
+ * Disable Names/PredicateName rubocop rule.
12
+ * Fix generated client tests when a request field name collides with a Ruby superclass method.
13
+
14
+ ### 0.6.8 / 2020-09-16
15
+
16
+ * Add samples tasks to generated gapic rakefiles.
17
+ * Disable Style/AsciiComments rule.
18
+
19
+ ### 0.6.7 / 2020-08-07
20
+
21
+ * Generated credentials config allows symbols.
22
+
23
+ ### 0.6.6 / 2020-08-05
24
+
25
+ * Use numeric error codes rather than strings in generated retry configs.
26
+
3
27
  ### 0.6.5 / 2020-07-16
4
28
 
5
29
  * Examples in auth, rakefile, and readme should pick a non-common service.
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Gapic
18
18
  module Generator
19
- VERSION = "0.6.5"
19
+ VERSION = "0.6.10"
20
20
  end
21
21
  end
@@ -15,6 +15,7 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require "gapic/generators/base_generator"
18
+ require "gapic/generators/default_generator_parameters"
18
19
  require "gapic/presenters"
19
20
 
20
21
  module Gapic
@@ -89,6 +90,12 @@ module Gapic
89
90
 
90
91
  # rubocop:enable all
91
92
 
93
+ # Schema of the parameters that the generator accepts
94
+ # @return [Gapic::Schema::ParameterSchema]
95
+ def self.parameter_schema
96
+ DefaultGeneratorParameters.default_schema
97
+ end
98
+
92
99
  private
93
100
 
94
101
  ##
@@ -0,0 +1,114 @@
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/schema/parameter_schema"
18
+
19
+ module Gapic
20
+ module Generators
21
+ # Contains the default generator's parameters
22
+ module DefaultGeneratorParameters
23
+ BOOL_PARAMETERS = [
24
+ ":gem.:free_tier",
25
+ ":gem.:yard_strict",
26
+ ":gem.:generic_endpoint"
27
+ ].freeze
28
+
29
+ STRING_PARAMETERS = [
30
+ ":gem.:name",
31
+ ":gem.:namespace",
32
+ ":gem.:title",
33
+ ":gem.:description",
34
+ ":gem.:summary",
35
+ ":gem.:homepage",
36
+ ":gem.:env_prefix",
37
+ ":gem.:version_dependencies",
38
+ ":gem.:migration_version",
39
+ ":gem.:product_documentation_url",
40
+ ":gem.:issue_tracker_url",
41
+ ":gem.:api_id",
42
+ ":gem.:api_shortname",
43
+ ":gem.:factory_method_suffix",
44
+ ":defaults.:service.:default_host",
45
+ "grpc_service_config"
46
+ ].freeze
47
+
48
+ ARRAY_PARAMETERS = [
49
+ ":defaults.:service.:oauth_scopes"
50
+ ].freeze
51
+
52
+ MAP_PARAMETERS = [
53
+ ":common_services",
54
+ ":overrides.:file_path",
55
+ ":overrides.:namespace",
56
+ ":overrides.:service",
57
+ ":gem.:extra_dependencies"
58
+ ].freeze
59
+
60
+ BOOL_PARAMETERS_ALIASES = {
61
+ "gem-free-tier" => ":gem.:free_tier",
62
+ "gem-yard-strict" => ":gem.:yard_strict",
63
+ "gem-generic-endpoint" => ":gem.:generic_endpoint"
64
+ }.freeze
65
+
66
+ STRING_PARAMETERS_ALIASES = {
67
+ "gem-name" => ":gem.:name",
68
+ "gem-namespace" => ":gem.:namespace",
69
+ "gem-title" => ":gem.:title",
70
+ "gem-description" => ":gem.:description",
71
+ "gem-summary" => ":gem.:summary",
72
+ "gem-homepage" => ":gem.:homepage",
73
+ "gem-env-prefix" => ":gem.:env_prefix",
74
+ "gem-wrapper-of" => ":gem.:version_dependencies",
75
+ "gem-migration-version" => ":gem.:migration_version",
76
+ "gem-product-url" => ":gem.:product_documentation_url",
77
+ "gem-issues-url" => ":gem.:issue_tracker_url",
78
+ "gem-api-id" => ":gem.:api_id",
79
+ "gem-api-shortname" => ":gem.:api_shortname",
80
+ "gem-factory-method-suffix" => ":gem.:factory_method_suffix",
81
+ "default-service-host" => ":defaults.:service.:default_host",
82
+ "grpc-service-config" => "grpc_service_config"
83
+ }.freeze
84
+
85
+ ARRAY_PARAMETERS_ALIASES = {
86
+ "default-oauth-scopes" => ":defaults.:service.:oauth_scopes"
87
+ }.freeze
88
+
89
+ MAP_PARAMETERS_ALIASES = {
90
+ "common-services" => ":common_services",
91
+ "file-path-override" => ":overrides.:file_path",
92
+ "namespace-override" => ":overrides.:namespace",
93
+ "service-override" => ":overrides.:service",
94
+ "gem-extra-dependencies" => ":gem.:extra_dependencies"
95
+ }.freeze
96
+
97
+ def self.default_schema
98
+ base_schema = Gapic::Schema::ParameterSchema.create(
99
+ bool_params_list: BOOL_PARAMETERS,
100
+ string_params_list: STRING_PARAMETERS,
101
+ array_params_list: ARRAY_PARAMETERS,
102
+ map_params_list: MAP_PARAMETERS
103
+ )
104
+
105
+ base_schema.extend_with_aliases(
106
+ bool_aliases: BOOL_PARAMETERS_ALIASES,
107
+ string_aliases: STRING_PARAMETERS_ALIASES,
108
+ array_aliases: ARRAY_PARAMETERS_ALIASES,
109
+ map_aliases: MAP_PARAMETERS_ALIASES
110
+ )
111
+ end
112
+ end
113
+ end
114
+ end
@@ -40,6 +40,31 @@ module Gapic
40
40
  MULTIPLIER_JSON_KEY = "backoffMultiplier"
41
41
  STATUS_CODES_JSON_KEY = "retryableStatusCodes"
42
42
 
43
+ # See https://grpc.github.io/grpc/core/md_doc_statuscodes.html for a
44
+ # list of error codes.
45
+ ERROR_CODE_MAPPING = [
46
+ "OK",
47
+ "CANCELLED",
48
+ "UNKNOWN",
49
+ "INVALID_ARGUMENT",
50
+ "DEADLINE_EXCEEDED",
51
+ "NOT_FOUND",
52
+ "ALREADY_EXISTS",
53
+ "PERMISSION_DENIED",
54
+ "RESOURCE_EXHAUSTED",
55
+ "FAILED_PRECONDITION",
56
+ "ABORTED",
57
+ "OUT_OF_RANGE",
58
+ "UNIMPLEMENTED",
59
+ "INTERNAL",
60
+ "UNAVAILABLE",
61
+ "DATA_LOSS",
62
+ "UNAUTHENTICATED"
63
+ ].freeze
64
+
65
+ ERROR_STRING_MAPPING = ERROR_CODE_MAPPING.each_with_index.each_with_object({}) do |(str, num), hash|
66
+ hash[str] = num
67
+ end.freeze
43
68
 
44
69
  ##
45
70
  # Parses ServiceConfig from a json of a GRPC service config
@@ -146,11 +171,26 @@ module Gapic
146
171
  initial_delay_seconds = parse_interval_seconds get(retry_policy_json, INITIAL_DELAY_JSON_KEY)
147
172
  max_delay_seconds = parse_interval_seconds get(retry_policy_json, MAX_DELAY_JSON_KEY)
148
173
  multiplier = get retry_policy_json, MULTIPLIER_JSON_KEY
149
- status_codes = get retry_policy_json, STATUS_CODES_JSON_KEY
174
+ status_codes = convert_codes get retry_policy_json, STATUS_CODES_JSON_KEY
150
175
 
151
176
  RetryPolicy.new initial_delay_seconds, max_delay_seconds, multiplier, status_codes
152
177
  end
153
178
 
179
+ ##
180
+ # Interpret input status codes. Convert strings to their associated integer codes.
181
+ #
182
+ def self.convert_codes input_codes
183
+ return nil if input_codes.nil?
184
+ Array(input_codes).map do |obj|
185
+ case obj
186
+ when String
187
+ ERROR_STRING_MAPPING[obj]
188
+ when Integer
189
+ obj
190
+ end
191
+ end.compact
192
+ end
193
+
154
194
  ##
155
195
  # Parses time expressed in secondds from the GRPC service config json
156
196
  # The time is encoded is a string as float or integer with a letter 's' afterwards
@@ -212,7 +252,7 @@ module Gapic
212
252
  end
213
253
 
214
254
  private_class_method :parse_service_names, :filter_service_method_names, :parse_config,
215
- :parse_retry_policy, :parse_interval_seconds, :valid_float?
255
+ :parse_retry_policy, :parse_interval_seconds, :valid_float?, :convert_codes
216
256
  end
217
257
  end
218
258
  end
@@ -80,9 +80,25 @@ module Gapic
80
80
  package_require + ".rb"
81
81
  end
82
82
 
83
+ def package_directory_name
84
+ package_require.split("/").last
85
+ end
86
+
83
87
  def empty?
84
88
  services.empty?
85
89
  end
90
+
91
+ def helpers_file_path
92
+ helpers_require + ".rb"
93
+ end
94
+
95
+ def helpers_file_name
96
+ "_helpers.rb"
97
+ end
98
+
99
+ def helpers_require
100
+ package_require + "/_helpers"
101
+ end
86
102
  end
87
103
  end
88
104
  end
@@ -16,6 +16,7 @@
16
16
 
17
17
  require "gapic/generator"
18
18
  require "gapic/schema"
19
+ require "gapic/schema/request_param_parser"
19
20
  require "google/protobuf/compiler/plugin.pb"
20
21
 
21
22
  module Gapic
@@ -27,6 +28,20 @@ module Gapic
27
28
  # Initializes the runner.
28
29
  # @param [Google::Protobuf::Compiler::CodeGeneratorRequest] request
29
30
  def initialize request
31
+ # parse the parameters that apply to runner and not to the api and exclude them from the request
32
+ runner_param_names = ["binary_output", "generator"]
33
+ runner_schema = Gapic::Schema::ParameterSchema.create(
34
+ string_params_list: runner_param_names
35
+ )
36
+
37
+ params = Gapic::Schema::RequestParamParser.parse_parameters_string request.parameter, param_schema: runner_schema
38
+ @binary_output_path = params.filter { |p| p.config_name == "binary_output" }.first&.config_value
39
+ @generator_type = params.filter { |p| p.config_name == "generator" }.first&.config_value
40
+
41
+ gapic_params = params.filter { |p| !runner_param_names.include? p.config_name }
42
+ # reconstruct the request parameter string without the runner parameters
43
+ request.parameter = Gapic::Schema::RequestParamParser.reconstruct_parameters_string gapic_params
44
+
30
45
  @request = request
31
46
  end
32
47
 
@@ -34,22 +49,22 @@ module Gapic
34
49
  # @param [String] generator_type
35
50
  # @return [Google::Protobuf::Compiler::CodeGeneratorResponse]
36
51
  def run generator_type: nil
37
- # Create an API Schema from the FileDescriptorProtos
38
- api = Gapic::Schema::Api.new request
39
-
40
- write_binary_file! api
52
+ # save the binary file if needed
53
+ write_binary_file
41
54
 
42
55
  # Retrieve generator type from protoc_options if not already provided.
43
- generator_type ||= api.protoc_options["generator"]
56
+ generator_type ||= @generator_type
44
57
  # Find the generator for the generator type.
45
58
  generator = Gapic::Generator.find generator_type
46
59
 
60
+ # Create an API Schema from the FileDescriptorProtos
61
+ api = Gapic::Schema::Api.new request, parameter_schema: generator.parameter_schema
62
+
47
63
  # Create and run the generator from the API.
48
64
  output_files = generator.new(api).generate
49
65
 
50
66
  # Create and write the response
51
- response = Google::Protobuf::Compiler::CodeGeneratorResponse.new \
52
- file: output_files
67
+ response = Google::Protobuf::Compiler::CodeGeneratorResponse.new file: output_files
53
68
  response.supported_features = Google::Protobuf::Compiler::CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL
54
69
  response
55
70
  end
@@ -64,15 +79,13 @@ module Gapic
64
79
 
65
80
  private
66
81
 
67
- def write_binary_file! api
68
- return unless api.protoc_options["binary_output"]
69
-
70
- # First, strip the binary_output parameter out so it doesn't get saved
71
- binary_file = api.protoc_options.delete "binary_output"
72
- request.parameter = api.protoc_parameter
82
+ # Save binary file with the request
83
+ # if the binary_output_path parameter is set
84
+ def write_binary_file
85
+ return unless @binary_output_path
73
86
 
74
87
  # Write binary file if the binary_output option is set
75
- File.binwrite binary_file, request.to_proto
88
+ File.binwrite @binary_output_path, request.to_proto
76
89
  end
77
90
  end
78
91
  end
@@ -16,7 +16,9 @@
16
16
 
17
17
  require "yaml"
18
18
  require "json"
19
+ require "gapic/generators/default_generator_parameters"
19
20
  require "gapic/schema/loader"
21
+ require "gapic/schema/request_param_parser"
20
22
  require "gapic/grpc_service_config/parser"
21
23
 
22
24
  module Gapic
@@ -44,9 +46,11 @@ module Gapic
44
46
  #
45
47
  # @param request [Google::Protobuf::Compiler::CodeGeneratorRequest]
46
48
  # The request object.
49
+ # @param parameter_schema [Gapic::Schema::ParameterSchema]
50
+ # The request parameters schema to use
47
51
  # @param error_output [IO] An IO to write any errors/warnings to.
48
52
  # @param configuration [Hash] Optional override of configuration.
49
- def initialize request, error_output: STDERR, configuration: nil
53
+ def initialize request, parameter_schema: nil, error_output: STDERR, configuration: nil
50
54
  @request = request
51
55
  loader = Loader.new
52
56
  @files = request.proto_file.map do |fd|
@@ -55,6 +59,9 @@ module Gapic
55
59
  @files.each { |f| f.parent = self }
56
60
  @configuration = configuration
57
61
  @resource_types = analyze_resources
62
+
63
+ parameter_schema ||= Gapic::Generators::DefaultGeneratorParameters.default_schema
64
+ @protoc_parameters = parse_parameter request.parameter, parameter_schema, error_output
58
65
  sanity_checks error_output
59
66
  end
60
67
 
@@ -116,33 +123,20 @@ module Gapic
116
123
 
117
124
  # Structured Hash representation of the parameter values.
118
125
  # @return [Hash]
119
- # A Hash of the request parameters.
120
126
  def protoc_options
121
127
  @protoc_options ||= begin
122
128
  result = {}
123
- parameters = parse_parameter request.parameter
124
- parameters.each do |param_array|
125
- key = param_array.first
126
- next if key.empty?
127
- value = param_array[1..-1]
128
- value = value.first if value.size == 1
129
- value = nil if value.empty?
130
- result[str_to_key(key)] = value
129
+ @protoc_parameters.each do |parameter|
130
+ result[str_to_key(parameter.config_name)] = parameter.config_value
131
131
  end
132
132
  result
133
133
  end
134
134
  end
135
135
 
136
- # Reconstructed string representation of the protoc options
136
+ # Reconstructed string representation of the protoc parameters
137
137
  # @return [String]
138
138
  def protoc_parameter
139
- protoc_options.map do |k, v|
140
- v = Array(v).map do |s|
141
- s.gsub("\\", "\\\\\\\\").gsub(",", "\\\\,").gsub("=", "\\\\=")
142
- end.join("=")
143
- k = key_to_str k
144
- "#{k}=#{v}"
145
- end.join ","
139
+ Gapic::Schema::RequestParamParser.reconstruct_parameters_string @protoc_parameters
146
140
  end
147
141
 
148
142
  # Structured representation of the samples configuration files.
@@ -353,20 +347,13 @@ module Gapic
353
347
 
354
348
  # Parse a comma-delimited list of equals-delimited lists of strings, while
355
349
  # mapping backslash-escaped commas and equal signs to literal characters.
356
- def parse_parameter str
357
- str.scan(/\\.|,|=|[^\\,=]+/)
358
- .each_with_object([[String.new]]) do |tok, arr|
359
- if tok == ","
360
- arr.append [String.new]
361
- elsif tok == "="
362
- arr.last.append String.new
363
- elsif tok.start_with? "\\"
364
- arr.last.last << tok[1]
365
- else
366
- arr.last.last << tok
367
- end
368
- arr
369
- end
350
+ # @param str [String]
351
+ # @param error_output [IO] Stream to write outputs to.
352
+ # @return [Array<Gapic::Schema::RequestParameter>]
353
+ def parse_parameter str, parameter_schema, error_output
354
+ Gapic::Schema::RequestParamParser.parse_parameters_string str,
355
+ param_schema: parameter_schema,
356
+ error_output: error_output
370
357
  end
371
358
 
372
359
  # split the string on periods, but map backslash-escaped periods to
@@ -0,0 +1,92 @@
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 Schema
19
+ # Contains information about known parameter names
20
+ # and the types expected to be parsed from the request options string
21
+ class ParameterSchema
22
+ attr_accessor :bool_params, :string_params, :array_params, :map_params
23
+
24
+ # Creates a schema with given alias-parameter maps
25
+ # @param bool_params [Hash{String => String}]
26
+ # @param string_params [Hash{String => String}]
27
+ # @param array_params [Hash{String => String}]
28
+ # @param map_params [Hash{String => String}]
29
+ def initialize bool_params = {}, string_params = {}, array_params = {}, map_params = {}
30
+ @bool_params = bool_params
31
+ @string_params = string_params
32
+ @array_params = array_params
33
+ @map_params = map_params
34
+ end
35
+
36
+ # Creates a schema from given parameter lists
37
+ # @param bool_params_list [Array<String>]
38
+ # @param string_params_list [Array<String>]
39
+ # @param array_params_list [Array<String>]
40
+ # @param map_params_list [Array<String>]
41
+ # @return Gapic::Schema::ParameterSchema
42
+ def self.create bool_params_list: [], string_params_list: [], array_params_list: [], map_params_list: []
43
+ bool_params = bool_params_list.map { |val| [val, val] }.to_h
44
+ string_params = string_params_list.map { |val| [val, val] }.to_h
45
+ array_params = array_params_list.map { |val| [val, val] }.to_h
46
+ map_params = map_params_list.map { |val| [val, val] }.to_h
47
+
48
+ ParameterSchema.new bool_params, string_params, array_params, map_params
49
+ end
50
+
51
+ # Creates a new schema from this by adding aliases to existing parameters
52
+ # @param bool_aliases [Hash{String => String}]
53
+ # @param string_aliases [Hash{String => String}]
54
+ # @param array_aliases [Hash{String => String}]
55
+ # @param map_aliases [Hash{String => String}]
56
+ # @return Gapic::Schema::ParameterSchema
57
+ def extend_with_aliases bool_aliases: {}, string_aliases: {}, array_aliases: {}, map_aliases: {}
58
+ bool_params = @bool_params
59
+ bool_aliases.each { |param_alias, param| bool_params[param_alias] = param if bool_params.key? param }
60
+
61
+ string_params = @string_params
62
+ string_aliases.each { |param_alias, param| string_params[param_alias] = param if string_params.key? param }
63
+
64
+ array_params = @array_params
65
+ array_aliases.each { |param_alias, param| array_params[param_alias] = param if array_params.key? param }
66
+
67
+ map_params = @map_params
68
+ map_aliases.each { |param_alias, param| map_params[param_alias] = param if map_params.key? param }
69
+
70
+ ParameterSchema.new bool_params, string_params, array_params, map_params
71
+ end
72
+
73
+ # Looks up a parameter by name (including aliases)
74
+ # and return a type label (or :unknown) and a configuration name
75
+ # @param param_name [String] Input parameter name
76
+ # @return [Array<Symbol, String>] An array of [:detected_type, config_parameter_name]
77
+ def schema_name_type_for param_name
78
+ if @bool_params.key? param_name
79
+ [:bool, @bool_params[param_name]]
80
+ elsif @string_params.key? param_name
81
+ [:string, @string_params[param_name]]
82
+ elsif @array_params.key? param_name
83
+ [:array, @array_params[param_name]]
84
+ elsif @map_params.key? param_name
85
+ [:map, @map_params[param_name]]
86
+ else
87
+ [:unknown, param_name]
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,126 @@
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/schema/request_parameter"
18
+ require "gapic/schema/parameter_schema"
19
+
20
+ module Gapic
21
+ module Schema
22
+ # Contains logic for parsing protoc request parameters
23
+ # from the plugin_opt command line
24
+ module RequestParamParser
25
+ class << self
26
+ # Unescapes a symbol from the string
27
+ # e.g. `'a\.b', '.' => 'a.b'`
28
+ # @param string [String] String to unescape
29
+ # @return [String] Unescaped string
30
+ def unescape string
31
+ string.gsub(/\\./) { |escaped| escaped[1] }
32
+ end
33
+
34
+ # Splits a string by an unescaped symbol
35
+ # e.g. `'a\.b.c.d\.e', '.' => ['a\.b', 'c', 'd\.e']`
36
+ # @param string [String] String to split
37
+ # @param symbol [String] Symbol to split by
38
+ # @param max_splits [Integer] Maximum amount of splits to perform; -1 for no limit
39
+ # @return [Array<String>] List of split string parts
40
+ def split_by_unescaped string, symbol, max_splits = -1
41
+ splits = 0
42
+ escaped_symbol = Regexp.escape symbol
43
+ string.scan(/\\.|#{escaped_symbol}|[^#{escaped_symbol}\\]+/).each_with_object([String.new]) do |tok, arr|
44
+ if tok == symbol && (max_splits.negative? || splits < max_splits)
45
+ arr.append String.new
46
+ splits += 1
47
+ else
48
+ arr.last << tok
49
+ end
50
+ arr
51
+ end
52
+ end
53
+
54
+ # Parse a comma-delimited list of equals-delimited lists of strings, while
55
+ # mapping backslash-escaped commas and equal signs to literal characters.
56
+ # @param str [String] String to parse
57
+ # @param param_schema [ParameterSchema] Parameter schema to use
58
+ # @param error_output [IO] Stream to write outputs to.
59
+ # @return [Array<RequestParameter>] List of parameters parsed
60
+ def parse_parameters_string str, param_schema: nil, error_output: nil
61
+ return [] if str.empty?
62
+ param_schema ||= Gapic::Generators::DefaultGeneratorParameters.default_schema
63
+
64
+ param_val_input_strings = split_by_unescaped str, ","
65
+ param_val_input_strings.map do |param_val_input_str|
66
+ param_name_input_esc, value_str = split_by_unescaped param_val_input_str, "=", 1
67
+ param_name_input = unescape param_name_input_esc
68
+ param_type, param_config_name = param_schema.schema_name_type_for param_name_input
69
+
70
+ if param_type == :bool && !["true", "false"].include?(unescape(value_str))
71
+ error_str = "WARNING: parameter #{param_name_input} (recognised as bool " \
72
+ "#{param_config_name}) will be discarded because of " \
73
+ "invalid value. Value should be either 'true' or 'false'."
74
+ error_output&.puts error_str
75
+ end
76
+
77
+ param_value = parse_param_value param_type, value_str
78
+
79
+ if param_value
80
+ RequestParameter.new param_val_input_str, param_name_input_esc, value_str, param_config_name, param_value
81
+ end
82
+ end.compact # known bool parameters with invalid values will not be added so we have to compact
83
+ end
84
+
85
+ # Take a list of parameters and re-create an input string
86
+ # that can be parsed into these parameters
87
+ # @param parameters [Array<RequestParameter>] List of gapic-generator parameters
88
+ # @return [String] an input string with parameters
89
+ def reconstruct_parameters_string parameters
90
+ parameters.map(&:input_str).join ","
91
+ end
92
+
93
+ private
94
+
95
+ # Parses param value depending on type
96
+ # @param param_type [Symbol]
97
+ # @param value_str [String]
98
+ # @return [String,Array<String>,Hash{String => String}]
99
+ def parse_param_value param_type, value_str
100
+ case param_type
101
+ when :array
102
+ # elements in the arrays are concatenated by `;`
103
+ # e.g. foo;bar;baz
104
+ array_value_strings = split_by_unescaped value_str, ";"
105
+ array_value_strings.map { |s| unescape s }
106
+ when :map
107
+ # elements in the maps are `=` - separated key-value pairs, concatenated by ';'
108
+ # e.g. foo=hoge;bar=piyo
109
+ keyvaluepair_strings = split_by_unescaped value_str, ";"
110
+ new_hash = keyvaluepair_strings.map do |kvp_str|
111
+ split_by_unescaped(kvp_str, "=", 1).map { |s| unescape s }
112
+ end
113
+ new_hash.to_h
114
+ when :bool
115
+ # bools should be either `true` or `false`
116
+ unesc_val = unescape value_str
117
+ unesc_val if ["true", "false"].include? unesc_val
118
+ else
119
+ # if it's an unknown type, just escape it without attempting to parse anything
120
+ unescape value_str
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,52 @@
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 Schema
19
+ # Encapsulates information that is parsed from a single command line parameter
20
+ # from the plugin_opt command line
21
+ class RequestParameter
22
+ attr_reader :input_str, :input_name, :input_value, :config_name, :config_value
23
+
24
+ # @param input_str [String] the input string containing parameter and value
25
+ # that the parameter and value were parsed from
26
+ # @param input_name [String] the name of the parameter as found in the input
27
+ # can be an alias to a known config parameter name
28
+ # @param input_value [String] the unescaped input value of the parameter as found in the input
29
+ # @param config_name [String] the known config parameter name as matched during parsing
30
+ # @param config_value [String,Array,Hash] the parsed and deserialized config value
31
+ def initialize input_str, input_name, input_value, config_name, config_value
32
+ @input_str = input_str
33
+ @input_name = input_name
34
+ @input_value = input_value
35
+ @config_name = config_name
36
+ @config_value = config_value
37
+ end
38
+
39
+ # The hash of input name-value
40
+ # @return [Hash {String => String}]
41
+ def to_input_h
42
+ { input_name => input_value }
43
+ end
44
+
45
+ # The hash of config name-value
46
+ # @return [Hash {String => String, Array, Hash}]
47
+ def to_config_h
48
+ { config_name => config_value }
49
+ end
50
+ end
51
+ end
52
+ end
@@ -25,6 +25,10 @@ Metrics/PerceivedComplexity:
25
25
  Naming/FileName:
26
26
  Exclude:
27
27
  - "lib/<%= gem.name %>.rb"
28
+ Naming/PredicateName:
29
+ Enabled: false
30
+ Style/AsciiComments:
31
+ Enabled: false
28
32
  Style/CaseEquality:
29
33
  Enabled: false
30
34
  Style/IfUnlessModifier:
@@ -15,3 +15,7 @@ require "<%= package.gem.version_require %>"
15
15
  <%- end -%>
16
16
  module <%= package.module_name %>
17
17
  end
18
+ <% @footer = capture do %>
19
+ helper_path = ::File.join __dir__, "<%= package.package_directory_name %>", "<%= package.helpers_file_name %>"
20
+ require "<%= package.helpers_require %>" if ::File.file? helper_path
21
+ <% end %>
@@ -1,3 +1,3 @@
1
1
  <%- assert_locals service -%>
2
- helper_path = ::File.join __dir__, "<%= service.service_directory_name%>", "helpers.rb"
2
+ helper_path = ::File.join __dir__, "<%= service.service_directory_name %>", "<%= service.helpers_file_name %>"
3
3
  require "<%= service.helpers_require %>" if ::File.file? helper_path
@@ -87,7 +87,7 @@ class Configuration
87
87
 
88
88
  config_attr :endpoint, <%= service.client_endpoint.inspect %>, ::String
89
89
  config_attr :credentials, nil do |value|
90
- allowed = [::String, ::Hash, ::Proc, ::Google::Auth::Credentials, ::Signet::OAuth2::Client, nil]
90
+ allowed = [::String, ::Hash, ::Proc, ::Symbol, ::Google::Auth::Credentials, ::Signet::OAuth2::Client, nil]
91
91
  allowed += [::GRPC::Core::Channel, ::GRPC::Core::ChannelCredentials] if defined? ::GRPC
92
92
  allowed.any? { |klass| klass === value }
93
93
  end
@@ -127,7 +127,7 @@ class Configuration
127
127
  # Each configuration object is of type `Gapic::Config::Method` and includes
128
128
  # the following configuration fields:
129
129
  #
130
- # * `timeout` (*type:* `Numeric`) - The call timeout in milliseconds
130
+ # * `timeout` (*type:* `Numeric`) - The call timeout in seconds
131
131
  # * `metadata` (*type:* `Hash{Symbol=>String}`) - Additional gRPC headers
132
132
  # * `retry_policy (*type:* `Hash`) - The retry policy. The policy fields
133
133
  # include the following keys:
@@ -87,13 +87,13 @@ def test_<%= method.name %>
87
87
  assert_kind_of <%= method.request_type %>, r
88
88
  <%- fields.each do |field| -%>
89
89
  <%- if field.message? && field.repeated? && !field.map? -%>
90
- assert_kind_of <%= field.type_name_full %>, r.<%= field.name %>.first
90
+ assert_kind_of <%= field.type_name_full %>, r["<%= field.name %>"].first
91
91
  <%- elsif field.map? -%>
92
- assert_equal(<%= field.default_value %>, r.<%= field.name %>.to_h)
92
+ assert_equal(<%= field.default_value %>, r["<%= field.name %>"].to_h)
93
93
  <%- elsif field.message? -%>
94
- assert_equal Gapic::Protobuf.coerce(<%= field.default_value %>, to: <%= field.type_name_full %>), r.<%= field.name %>
94
+ assert_equal Gapic::Protobuf.coerce(<%= field.default_value %>, to: <%= field.type_name_full %>), r["<%= field.name %>"]
95
95
  <%- else -%>
96
- assert_equal <%= field.default_value %>, r.<%= field.name %>
96
+ assert_equal <%= field.default_value %>, r["<%= field.name %>"]
97
97
  <%- end -%>
98
98
  <%- if field.oneof? && !field.proto3_optional? -%>
99
99
  assert_equal :<%= field.name %>, r.<%= field.oneof_name %>
@@ -71,13 +71,13 @@ def test_<%= method.name %>
71
71
  assert_kind_of <%= method.request_type %>, r
72
72
  <%- fields.each do |field| -%>
73
73
  <%- if field.message? && field.repeated? && !field.map? -%>
74
- assert_kind_of <%= field.type_name_full %>, r.<%= field.name %>.first
74
+ assert_kind_of <%= field.type_name_full %>, r["<%= field.name %>"].first
75
75
  <%- elsif field.map? -%>
76
- assert_equal(<%= field.default_value %>, r.<%= field.name %>.to_h)
76
+ assert_equal(<%= field.default_value %>, r["<%= field.name %>"].to_h)
77
77
  <%- elsif field.message? -%>
78
- assert_equal Gapic::Protobuf.coerce(<%= field.default_value %>, to: <%= field.type_name_full %>), r.<%= field.name %>
78
+ assert_equal Gapic::Protobuf.coerce(<%= field.default_value %>, to: <%= field.type_name_full %>), r["<%= field.name %>"]
79
79
  <%- else -%>
80
- assert_equal <%= field.default_value %>, r.<%= field.name %>
80
+ assert_equal <%= field.default_value %>, r["<%= field.name %>"]
81
81
  <%- end -%>
82
82
  <%- if field.oneof? && !field.proto3_optional? -%>
83
83
  assert_equal :<%= field.name %>, r.<%= field.oneof_name %>
@@ -18,13 +18,13 @@ def test_<%= method.name %>
18
18
  assert_kind_of <%= method.request_type %>, request
19
19
  <%- fields.each do |field| -%>
20
20
  <%- if field.message? && field.repeated? && !field.map? -%>
21
- assert_kind_of <%= field.type_name_full %>, request.<%= field.name %>.first
21
+ assert_kind_of <%= field.type_name_full %>, request["<%= field.name %>"].first
22
22
  <%- elsif field.map? -%>
23
- assert_equal(<%= field.default_value %>, request.<%= field.name %>.to_h)
23
+ assert_equal(<%= field.default_value %>, request["<%= field.name %>"].to_h)
24
24
  <%- elsif field.message? -%>
25
- assert_equal Gapic::Protobuf.coerce(<%= field.default_value %>, to: <%= field.type_name_full %>), request.<%= field.name %>
25
+ assert_equal Gapic::Protobuf.coerce(<%= field.default_value %>, to: <%= field.type_name_full %>), request["<%= field.name %>"]
26
26
  <%- else -%>
27
- assert_equal <%= field.default_value %>, request.<%= field.name %>
27
+ assert_equal <%= field.default_value %>, request["<%= field.name %>"]
28
28
  <%- end -%>
29
29
  <%- if field.oneof? && !field.proto3_optional? -%>
30
30
  assert_equal :<%= field.name %>, request.<%= field.oneof_name %>
@@ -18,13 +18,13 @@ def test_<%= method.name %>
18
18
  assert_kind_of <%= method.request_type %>, request
19
19
  <%- fields.each do |field| -%>
20
20
  <%- if field.message? && field.repeated? && !field.map? -%>
21
- assert_kind_of <%= field.type_name_full %>, request.<%= field.name %>.first
21
+ assert_kind_of <%= field.type_name_full %>, request["<%= field.name %>"].first
22
22
  <%- elsif field.map? -%>
23
- assert_equal(<%= field.default_value %>, request.<%= field.name %>.to_h)
23
+ assert_equal(<%= field.default_value %>, request["<%= field.name %>"].to_h)
24
24
  <%- elsif field.message? -%>
25
- assert_equal Gapic::Protobuf.coerce(<%= field.default_value %>, to: <%= field.type_name_full %>), request.<%= field.name %>
25
+ assert_equal Gapic::Protobuf.coerce(<%= field.default_value %>, to: <%= field.type_name_full %>), request["<%= field.name %>"]
26
26
  <%- else -%>
27
- assert_equal <%= field.default_value %>, request.<%= field.name %>
27
+ assert_equal <%= field.default_value %>, request["<%= field.name %>"]
28
28
  <%- end -%>
29
29
  <%- if field.oneof? && !field.proto3_optional? -%>
30
30
  assert_equal :<%= field.name %>, request.<%= field.oneof_name %>
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.5
4
+ version: 0.6.10
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-07-20 00:00:00.000000000 Z
13
+ date: 2021-01-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: actionpack
@@ -196,6 +196,7 @@ files:
196
196
  - lib/gapic/generator/version.rb
197
197
  - lib/gapic/generators/base_generator.rb
198
198
  - lib/gapic/generators/default_generator.rb
199
+ - lib/gapic/generators/default_generator_parameters.rb
199
200
  - lib/gapic/grpc_service_config/method_config.rb
200
201
  - lib/gapic/grpc_service_config/parser.rb
201
202
  - lib/gapic/grpc_service_config/parsing_error.rb
@@ -225,6 +226,9 @@ files:
225
226
  - lib/gapic/schema.rb
226
227
  - lib/gapic/schema/api.rb
227
228
  - lib/gapic/schema/loader.rb
229
+ - lib/gapic/schema/parameter_schema.rb
230
+ - lib/gapic/schema/request_param_parser.rb
231
+ - lib/gapic/schema/request_parameter.rb
228
232
  - lib/gapic/schema/wrappers.rb
229
233
  - lib/gapic/uri_template.rb
230
234
  - lib/gapic/uri_template/parser.rb
@@ -343,7 +347,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
343
347
  - !ruby/object:Gem::Version
344
348
  version: '0'
345
349
  requirements: []
346
- rubygems_version: 3.0.3
350
+ rubygems_version: 3.1.2
347
351
  signing_key:
348
352
  specification_version: 4
349
353
  summary: An API Client Generator for Ruby in Ruby!