functions_framework 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 817129c1773079fed039152996a18e91a054241940b8d6e3437cb66e10046304
4
- data.tar.gz: ff3f61597726b60241e8b528ef520641fa3f08ddb7adcdfb32f9413fcb125f45
3
+ metadata.gz: 370556a72cd31e4d24499b0715ca7f96a0598cb856fb28fed3d3eaabee0a80ae
4
+ data.tar.gz: 04a24cf1e2f205fe124eb0bda891f647177b93c43ba1c2286ed52ffbad18cb1d
5
5
  SHA512:
6
- metadata.gz: 7396117d6e94bec87c70c697c7364b9256c7575f61c7259eb25df65694e9627b6c33a93e0caaea5d9d7955707e731eaddc27b90d4595f0029d181fc6cc18bfdf
7
- data.tar.gz: 8eb929ace2a49ae764f5de0fef6dd7e0d668c80864368ad2379d0e52a89a44c7a3514e92dc02802d940374808a271a89f3076f1c8f3d0a532204118615e0c1af
6
+ metadata.gz: 34d91fa0417632a253ddba1db7aa85f54697eb645caaaf96c9253a36fca241bca80bf17a40796dd5c8521d2c7bbe04ff23353764491d28b5e4335e0ee022f05a
7
+ data.tar.gz: 0d8d59ef3e45d3980136d7015e8066052bffe3942c442f715368dcf6ac5dd98b0cb282c313fa1a387ac70514747701e75c879c549faa9802444fe6b4d56115c7
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ### v0.5.0 / 2020-07-09
4
+
5
+ * Removed embedded CloudEvents classes and added the official CloudEvents SDK as a dependency. A `FunctionsFramework::CloudEvents` alias provides backward compatibility.
6
+
3
7
  ### v0.4.1 / 2020-07-08
4
8
 
5
9
  * Fixed unsupported signal error on Windows.
data/README.md CHANGED
@@ -60,7 +60,7 @@ Create a `Gemfile` listing the Functions Framework as a dependency:
60
60
  ```ruby
61
61
  # Gemfile
62
62
  source "https://rubygems.org"
63
- gem "functions_framework", "~> 0.4"
63
+ gem "functions_framework", "~> 0.5"
64
64
  ```
65
65
 
66
66
  Create a file called `app.rb` and include the following code. This defines a
@@ -64,7 +64,7 @@ Create a `Gemfile` listing the Functions Framework as a dependency:
64
64
  ```ruby
65
65
  # Gemfile
66
66
  source "https://rubygems.org"
67
- gem "functions_framework", "~> 0.4"
67
+ gem "functions_framework", "~> 0.5"
68
68
  ```
69
69
 
70
70
  Create a file called `app.rb` and include the following code. This defines a
@@ -112,7 +112,7 @@ dependency on Sinatra in your `Gemfile`:
112
112
  ```ruby
113
113
  # Gemfile
114
114
  source "https://rubygems.org"
115
- gem "functions_framework", "~> 0.4"
115
+ gem "functions_framework", "~> 0.5"
116
116
  gem "sinatra", "~> 2.0"
117
117
  ```
118
118
 
@@ -158,9 +158,9 @@ end
158
158
  ```
159
159
 
160
160
  The event parameter will be either a
161
- [CloudEvents V0.3 Event](https://rubydoc.info/gems/functions_framework/FunctionsFramework/CloudEvents/Event/V0)
161
+ [CloudEvents V0.3 Event](https://rubydoc.info/gems/cloud_events/CloudEvents/Event/V0)
162
162
  object ([see spec](https://github.com/cloudevents/spec/blob/v0.3/spec.md)) or a
163
- [CloudEvents V1.0 Event](https://rubydoc.info/gems/functions_framework/FunctionsFramework/CloudEvents/Event/V1)
163
+ [CloudEvents V1.0 Event](https://rubydoc.info/gems/cloud_events/CloudEvents/Event/V1)
164
164
  object ([see spec](https://github.com/cloudevents/spec/blob/v1.0/spec.md)).
165
165
 
166
166
  Some Google Cloud services send events in a legacy event format that was defined
@@ -236,7 +236,7 @@ A simple project might look like this:
236
236
  ```ruby
237
237
  # Gemfile
238
238
  source "https://rubygems.org"
239
- gem "functions_framework", "~> 0.4"
239
+ gem "functions_framework", "~> 0.5"
240
240
  ```
241
241
 
242
242
  ```ruby
@@ -14,7 +14,8 @@
14
14
 
15
15
  require "logger"
16
16
 
17
- require "functions_framework/cloud_events"
17
+ require "cloud_events"
18
+
18
19
  require "functions_framework/function"
19
20
  require "functions_framework/legacy_event_converter"
20
21
  require "functions_framework/registry"
@@ -44,10 +45,6 @@ require "functions_framework/version"
44
45
  #
45
46
  # Here is a roadmap to the internal modules in the Ruby functions framework.
46
47
  #
47
- # * {FunctionsFramework::CloudEvents} provides an implementation of the
48
- # [CloudEvents](https://cloudevents.io) specification. In particular, if
49
- # you define an event function, you will receive the event as a
50
- # {FunctionsFramework::CloudEvents::Event} object.
51
48
  # * {FunctionsFramework::CLI} is the implementation of the
52
49
  # `functions-framework-ruby` executable. Most apps will not need to interact
53
50
  # with this class directly.
@@ -94,6 +91,12 @@ module FunctionsFramework
94
91
  #
95
92
  DEFAULT_SOURCE = "./app.rb".freeze
96
93
 
94
+ ##
95
+ # The CloudEvents implementation was extracted to become the official
96
+ # CloudEvents SDK. This alias is left here for backward compatibility.
97
+ #
98
+ CloudEvents = ::CloudEvents
99
+
97
100
  class << self
98
101
  ##
99
102
  # The "global" registry that holds events defined by the
@@ -144,7 +147,8 @@ module FunctionsFramework
144
147
  #
145
148
  # You must provide a name for the function, and a block that implemets the
146
149
  # function. The block should take one argument: the event object of type
147
- # {FunctionsFramework::CloudEvents::Event}. Any return value is ignored.
150
+ # [`CloudEvents::Event`](https://rubydoc.info/gems/cloud_events/CloudEvents/Event).
151
+ # Any return value is ignored.
148
152
  #
149
153
  # ## Example
150
154
  #
@@ -23,8 +23,9 @@ module FunctionsFramework
23
23
  # `Rack::Request` argument and returns one of various HTTP response types.
24
24
  # See {FunctionsFramework::Registry.add_http}. For a function of type
25
25
  # `:cloud_event`, the `call` method takes a single
26
- # {FunctionsFramework::CloudEvents::Event CloudEvent} argument, and does not
27
- # return a value. See {FunctionsFramework::Registry.add_cloud_event}.
26
+ # [CloudEvent](https://rubydoc.info/gems/cloud_events/CloudEvents/Event)
27
+ # argument, and does not return a value.
28
+ # See {FunctionsFramework::Registry.add_cloud_event}.
28
29
  #
29
30
  # If a callable object is provided directly, its `call` method is invoked for
30
31
  # every function execution. Note that this means it may be called multiple
@@ -23,12 +23,11 @@ module FunctionsFramework
23
23
  # Decode an event from the given Rack environment hash.
24
24
  #
25
25
  # @param env [Hash] The Rack environment
26
- # @return [FunctionsFramework::CloudEvents::Event] if the request could
27
- # be converted
26
+ # @return [::CloudEvents::Event] if the request could be converted
28
27
  # @return [nil] if the event format was not recognized.
29
28
  #
30
29
  def decode_rack_env env
31
- content_type = CloudEvents::ContentType.new env["CONTENT_TYPE"]
30
+ content_type = ::CloudEvents::ContentType.new env["CONTENT_TYPE"]
32
31
  return nil unless content_type.media_type == "application" && content_type.subtype_base == "json"
33
32
  input = read_input_json env["rack.input"], content_type.charset
34
33
  return nil unless input
@@ -85,14 +84,14 @@ module FunctionsFramework
85
84
  return nil unless type && source
86
85
  ce_data = convert_data context[:service], data
87
86
  content_type = "application/json; charset=#{charset}"
88
- CloudEvents::Event.new id: context[:id],
89
- source: source,
90
- type: type,
91
- spec_version: "1.0",
92
- data_content_type: content_type,
93
- data: ce_data,
94
- subject: subject,
95
- time: context[:timestamp]
87
+ ::CloudEvents::Event.new id: context[:id],
88
+ source: source,
89
+ type: type,
90
+ spec_version: "1.0",
91
+ data_content_type: content_type,
92
+ data: ce_data,
93
+ subject: subject,
94
+ time: context[:timestamp]
96
95
  end
97
96
 
98
97
  def convert_source service, resource
@@ -80,7 +80,8 @@ module FunctionsFramework
80
80
  #
81
81
  # You must provide a name for the function, and a block that implemets the
82
82
  # function. The block should take _one_ argument: the event object of type
83
- # {FunctionsFramework::CloudEvents::Event}. Any return value is ignored.
83
+ # [`CloudEvents::Event`](https://rubydoc.info/gems/cloud_events/CloudEvents/Event).
84
+ # Any return value is ignored.
84
85
  #
85
86
  # @param name [String] The function name
86
87
  # @param block [Proc] The function code as a proc
@@ -344,7 +344,7 @@ module FunctionsFramework
344
344
  string_response response, "text/plain", 200
345
345
  when ::Hash
346
346
  string_response ::JSON.dump(response), "application/json", 200
347
- when CloudEvents::CloudEventsError
347
+ when ::CloudEvents::CloudEventsError
348
348
  cloud_events_error_response response
349
349
  when ::StandardError
350
350
  error_response "#{response.class}: #{response.message}\n#{response.backtrace}\n"
@@ -405,7 +405,7 @@ module FunctionsFramework
405
405
  def initialize function, config
406
406
  super config
407
407
  @function = function
408
- @cloud_events = CloudEvents::HttpBinding.default
408
+ @cloud_events = ::CloudEvents::HttpBinding.default
409
409
  @legacy_events = LegacyEventConverter.new
410
410
  end
411
411
 
@@ -415,11 +415,11 @@ module FunctionsFramework
415
415
  event = decode_event env
416
416
  response =
417
417
  case event
418
- when CloudEvents::Event
418
+ when ::CloudEvents::Event
419
419
  handle_cloud_event event, logger
420
420
  when ::Array
421
- CloudEvents::HttpContentError.new "Batched CloudEvents are not supported"
422
- when CloudEvents::CloudEventsError
421
+ ::CloudEvents::HttpContentError.new "Batched CloudEvents are not supported"
422
+ when ::CloudEvents::CloudEventsError
423
423
  event
424
424
  else
425
425
  raise "Unexpected event type: #{event.class}"
@@ -432,8 +432,8 @@ module FunctionsFramework
432
432
  def decode_event env
433
433
  @cloud_events.decode_rack_env(env) ||
434
434
  @legacy_events.decode_rack_env(env) ||
435
- raise(CloudEvents::HttpContentError, "Unrecognized event format")
436
- rescue CloudEvents::CloudEventsError => e
435
+ raise(::CloudEvents::HttpContentError, "Unrecognized event format")
436
+ rescue ::CloudEvents::CloudEventsError => e
437
437
  e
438
438
  end
439
439
 
@@ -100,7 +100,7 @@ module FunctionsFramework
100
100
  # be of type :cloud_event`.
101
101
  #
102
102
  # @param name [String] The name of the function to call
103
- # @param event [FunctionsFramework::CloudEvets::Event] The event to send
103
+ # @param event [::CloudEvents::Event] The event to send
104
104
  # @return [nil]
105
105
  #
106
106
  def call_event name, event
@@ -174,23 +174,35 @@ module FunctionsFramework
174
174
  # @param source [String,URI] Event source (optional)
175
175
  # @param type [String] Event type (optional)
176
176
  # @param spec_version [String] Spec version (optional)
177
- # @param data_content_type [String,FunctionsFramework::CloudEvents::ContentType]
177
+ # @param data_content_type [String,::CloudEvents::ContentType]
178
178
  # Content type for the data (optional)
179
179
  # @param data_schema [String,URI] Data schema (optional)
180
180
  # @param subject [String] Subject (optional)
181
181
  # @param time [String,DateTime] Event timestamp (optional)
182
- # @return [FunctionsFramework::CloudEvents::Event]
182
+ # @return [::CloudEvents::Event]
183
183
  #
184
184
  def make_cloud_event data,
185
- id: nil, source: nil, type: nil, spec_version: nil,
186
- data_content_type: nil, data_schema: nil, subject: nil, time: nil
185
+ id: nil,
186
+ source: nil,
187
+ type: nil,
188
+ spec_version: nil,
189
+ data_content_type: nil,
190
+ data_schema: nil,
191
+ subject: nil,
192
+ time: nil
187
193
  id ||= "random-id-#{rand 100_000_000}"
188
194
  source ||= "functions-framework-testing"
189
195
  type ||= "com.example.test"
190
196
  spec_version ||= "1.0"
191
- CloudEvents::Event.new id: id, source: source, type: type, spec_version: spec_version,
192
- data_content_type: data_content_type, data_schema: data_schema,
193
- subject: subject, time: time, data: data
197
+ ::CloudEvents::Event.new id: id,
198
+ source: source,
199
+ type: type,
200
+ spec_version: spec_version,
201
+ data_content_type: data_content_type,
202
+ data_schema: data_schema,
203
+ subject: subject,
204
+ time: time,
205
+ data: data
194
206
  end
195
207
 
196
208
  extend self
@@ -17,5 +17,5 @@ module FunctionsFramework
17
17
  # Version of the Ruby Functions Framework
18
18
  # @return [String]
19
19
  #
20
- VERSION = "0.4.1".freeze
20
+ VERSION = "0.5.0".freeze
21
21
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: functions_framework
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-08 00:00:00.000000000 Z
11
+ date: 2020-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cloud_events
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.1'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: puma
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -60,15 +74,6 @@ files:
60
74
  - docs/writing-functions.md
61
75
  - lib/functions_framework.rb
62
76
  - lib/functions_framework/cli.rb
63
- - lib/functions_framework/cloud_events.rb
64
- - lib/functions_framework/cloud_events/content_type.rb
65
- - lib/functions_framework/cloud_events/errors.rb
66
- - lib/functions_framework/cloud_events/event.rb
67
- - lib/functions_framework/cloud_events/event/field_interpreter.rb
68
- - lib/functions_framework/cloud_events/event/v0.rb
69
- - lib/functions_framework/cloud_events/event/v1.rb
70
- - lib/functions_framework/cloud_events/http_binding.rb
71
- - lib/functions_framework/cloud_events/json_format.rb
72
77
  - lib/functions_framework/function.rb
73
78
  - lib/functions_framework/legacy_event_converter.rb
74
79
  - lib/functions_framework/registry.rb
@@ -82,7 +87,7 @@ metadata:
82
87
  changelog_uri: https://github.com/GoogleCloudPlatform/functions-framework-ruby/blob/master/CHANGELOG.md
83
88
  source_code_uri: https://github.com/GoogleCloudPlatform/functions-framework-ruby
84
89
  bug_tracker_uri: https://github.com/GoogleCloudPlatform/functions-framework-ruby/issues
85
- documentation_uri: https://rubydoc.info/gems/functions_framework/0.4.1
90
+ documentation_uri: https://rubydoc.info/gems/functions_framework/0.5.0
86
91
  post_install_message:
87
92
  rdoc_options: []
88
93
  require_paths:
@@ -1,45 +0,0 @@
1
- # Copyright 2020 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # https://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- require "functions_framework/cloud_events/content_type"
16
- require "functions_framework/cloud_events/errors"
17
- require "functions_framework/cloud_events/event"
18
- require "functions_framework/cloud_events/http_binding"
19
- require "functions_framework/cloud_events/json_format"
20
-
21
- module FunctionsFramework
22
- ##
23
- # CloudEvents implementation.
24
- #
25
- # This is a Ruby implementation of the [CloudEvents](https://cloudevents.io)
26
- # specification. It supports both
27
- # [CloudEvents 0.3](https://github.com/cloudevents/spec/blob/v0.3/spec.md) and
28
- # [CloudEvents 1.0](https://github.com/cloudevents/spec/blob/v1.0/spec.md).
29
- #
30
- module CloudEvents
31
- # @private
32
- SUPPORTED_SPEC_VERSIONS = ["0.3", "1.0"].freeze
33
-
34
- class << self
35
- ##
36
- # The spec versions supported by this implementation.
37
- #
38
- # @return [Array<String>]
39
- #
40
- def supported_spec_versions
41
- SUPPORTED_SPEC_VERSIONS
42
- end
43
- end
44
- end
45
- end
@@ -1,222 +0,0 @@
1
- # Copyright 2020 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # https://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- module FunctionsFramework
16
- module CloudEvents
17
- ##
18
- # A parsed content-type header.
19
- #
20
- # This object represents the information contained in a Content-Type,
21
- # obtained by parsing the header according to RFC 2045.
22
- #
23
- # Case-insensitive fields, such as media_type and subtype, are normalized
24
- # to lower case.
25
- #
26
- # If parsing fails, this class will try to get as much information as it
27
- # can, and fill the rest with defaults as recommended in RFC 2045 sec 5.2.
28
- # In case of a parsing error, the {#error_message} field will be set.
29
- #
30
- class ContentType
31
- ##
32
- # Parse the given header value.
33
- #
34
- # @param string [String] Content-Type header value in RFC 2045 format
35
- #
36
- def initialize string
37
- @string = string
38
- @media_type = "text"
39
- @subtype_base = @subtype = "plain"
40
- @subtype_format = nil
41
- @params = []
42
- @charset = "us-ascii"
43
- @error_message = nil
44
- parse consume_comments string.strip
45
- @canonical_string = "#{@media_type}/#{@subtype}" +
46
- @params.map { |k, v| "; #{k}=#{maybe_quote v}" }.join
47
- end
48
-
49
- ##
50
- # The original header content string.
51
- # @return [String]
52
- #
53
- attr_reader :string
54
- alias to_s string
55
-
56
- ##
57
- # A "canonical" header content string with spacing and capitalization
58
- # normalized.
59
- # @return [String]
60
- #
61
- attr_reader :canonical_string
62
-
63
- ##
64
- # The media type.
65
- # @return [String]
66
- #
67
- attr_reader :media_type
68
-
69
- ##
70
- # The entire content subtype (which could include an extension delimited
71
- # by a plus sign).
72
- # @return [String]
73
- #
74
- attr_reader :subtype
75
-
76
- ##
77
- # The portion of the content subtype before any plus sign.
78
- # @return [String]
79
- #
80
- attr_reader :subtype_base
81
-
82
- ##
83
- # The portion of the content subtype after any plus sign, or nil if there
84
- # is no plus sign in the subtype.
85
- # @return [String,nil]
86
- #
87
- attr_reader :subtype_format
88
-
89
- ##
90
- # An array of parameters, each element as a two-element array of the
91
- # parameter name and value.
92
- # @return [Array<Array(String,String)>]
93
- #
94
- attr_reader :params
95
-
96
- ##
97
- # The charset, defaulting to "us-ascii" if none is explicitly set.
98
- # @return [String]
99
- #
100
- attr_reader :charset
101
-
102
- ##
103
- # The error message when parsing, or `nil` if there was no error message.
104
- # @return [String,nil]
105
- #
106
- attr_reader :error_message
107
-
108
- ##
109
- # An array of values for the given parameter name
110
- # @param key [String]
111
- # @return [Array<String>]
112
- #
113
- def param_values key
114
- key = key.downcase
115
- @params.inject([]) { |a, (k, v)| key == k ? a << v : a }
116
- end
117
-
118
- ## @private
119
- def == other
120
- other.is_a?(ContentType) && canonical_string == other.canonical_string
121
- end
122
- alias eql? ==
123
-
124
- ## @private
125
- def hash
126
- canonical_string.hash
127
- end
128
-
129
- ## @private
130
- class ParseError < ::StandardError
131
- end
132
-
133
- private
134
-
135
- def parse str
136
- @media_type, str = consume_token str, downcase: true, error_message: "Failed to parse media type"
137
- str = consume_special str, "/"
138
- @subtype, str = consume_token str, downcase: true, error_message: "Failed to parse subtype"
139
- @subtype_base, @subtype_format = @subtype.split "+", 2
140
- until str.empty?
141
- str = consume_special str, ";"
142
- name, str = consume_token str, downcase: true, error_message: "Faled to parse attribute name"
143
- str = consume_special str, "=", error_message: "Failed to find value for attribute #{name}"
144
- val, str = consume_token_or_quoted str, error_message: "Failed to parse value for attribute #{name}"
145
- @params << [name, val]
146
- @charset = val if name == "charset"
147
- end
148
- rescue ParseError => e
149
- @error_message = e.message
150
- end
151
-
152
- def consume_token str, downcase: false, error_message: nil
153
- match = /^([\w!#\$%&'\*\+\.\^`\{\|\}-]+)(.*)$/.match str
154
- raise ParseError, error_message || "Expected token" unless match
155
- token = match[1]
156
- token.downcase! if downcase
157
- str = consume_comments match[2].strip
158
- [token, str]
159
- end
160
-
161
- def consume_special str, expected, error_message: nil
162
- raise ParseError, error_message || "Expected #{expected.inspect}" unless str.start_with? expected
163
- consume_comments str[1..-1].strip
164
- end
165
-
166
- def consume_token_or_quoted str, error_message: nil
167
- return consume_token str unless str.start_with? '"'
168
- arr = []
169
- index = 1
170
- loop do
171
- char = str[index]
172
- case char
173
- when nil
174
- raise ParseError, error_message || "Quoted-string never finished"
175
- when "\""
176
- break
177
- when "\\"
178
- char = str[index + 1]
179
- raise ParseError, error_message || "Quoted-string never finished" unless char
180
- arr << char
181
- index += 2
182
- else
183
- arr << char
184
- index += 1
185
- end
186
- end
187
- index += 1
188
- str = consume_comments str[index..-1].strip
189
- [arr.join, str]
190
- end
191
-
192
- def consume_comments str
193
- return str unless str.start_with? "("
194
- index = 1
195
- loop do
196
- char = str[index]
197
- case char
198
- when nil
199
- raise ParseError, "Comment never finished"
200
- when ")"
201
- break
202
- when "\\"
203
- index += 2
204
- when "("
205
- str = consume_comments str[index..-1]
206
- index = 0
207
- else
208
- index += 1
209
- end
210
- end
211
- index += 1
212
- consume_comments str[index..-1].strip
213
- end
214
-
215
- def maybe_quote str
216
- return str if /^[\w!#\$%&'\*\+\.\^`\{\|\}-]+$/ =~ str
217
- str = str.gsub("\\", "\\\\\\\\").gsub("\"", "\\\\\"")
218
- "\"#{str}\""
219
- end
220
- end
221
- end
222
- end