sinatra 3.2.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6eddf8c0c677b8b8b7f15bb03834147034ead41bc6310bf773ac84712bb43a14
4
- data.tar.gz: c35de3457f199d57a3c8a4419bd0ad113df38ba071cfffbcc79311db910bc1cb
3
+ metadata.gz: 71d0bb379c736d6c251ceb424cac84dbe3a8b22d80a54473a0af1085b93b7dbf
4
+ data.tar.gz: 489d48a5e4f934127e04cdafa2d0d582c5143cc2a8f476239ea5b5b0f0e492c9
5
5
  SHA512:
6
- metadata.gz: 33e0785425af5a32c7e09d95e2d11e02d83cdda1d907b34197c63642bfec81cd04a40ffc2e25486fe45af66d9a681f57c41d083d7bc56f24b69f1cf4b3a478f6
7
- data.tar.gz: 6aa65f3b65c819171bcadb61a3a43c3ff7af748d29a9177dbd02549229e3b9fa64b338d0404383b97615e74aa5381dd8a4c997edbf86ca0e8a2970e0213b2ece
6
+ metadata.gz: fbe92c1867d3ebe8ddc3f707c4e9f9cf2b68bddf2556164b85083ac635650725d63f8c847b4c70d0ad2abf6793b5f1054918b0b7c4e04d303119867be84c3253
7
+ data.tar.gz: 0727d88e9f5574c304dd3f31c6107a2b3e1cde96914e258c86fee529a1e922b0ff1d023f109fcc3b232f010ae21d9bdb4c365001dc7c3f658c0bd75b95e8d24d
data/CHANGELOG.md CHANGED
@@ -1,6 +1,27 @@
1
- ## Unreleased
1
+ ## 4.0.0. / 2024-01-19
2
2
 
3
- * _Your new feature here._
3
+ * New: Add support for Rack 3 ([#1857])
4
+ * Note: you may want to read the [Rack 3 Upgrade Guide]
5
+
6
+ * Require Ruby 2.7.8 as minimum Ruby version ([#1993])
7
+
8
+ * Breaking change: Drop support for Rack 2 ([#1857])
9
+ * Note: when using Sinatra to start the web server, you now need the `rackup` gem installed
10
+
11
+ * Breaking change: Remove the `IndifferentHash` initializer ([#1982])
12
+
13
+ * Breaking change: Disable `session_hijacking` protection by default ([#1984])
14
+
15
+ * Breaking change: Remove `Rack::Protection::EncryptedCookie` ([#1989])
16
+ * Note: cookies are still encrypted (by [`Rack::Session::Cookie`])
17
+
18
+ [#1857]: https://github.com/sinatra/sinatra/pull/1857
19
+ [#1993]: https://github.com/sinatra/sinatra/pull/1993
20
+ [#1982]: https://github.com/sinatra/sinatra/pull/1982
21
+ [#1984]: https://github.com/sinatra/sinatra/pull/1984
22
+ [#1989]: https://github.com/sinatra/sinatra/pull/1989
23
+ [`Rack::Session::Cookie`]: https://github.com/rack/rack-session
24
+ [Rack 3 Upgrade Guide]: https://github.com/rack/rack/blob/main/UPGRADE-GUIDE.md
4
25
 
5
26
  ## 3.2.0 / 2023-12-29
6
27
 
@@ -23,7 +44,7 @@
23
44
  [#1949]: https://github.com/sinatra/sinatra/pull/1949
24
45
  [#1952]: https://github.com/sinatra/sinatra/pull/1952
25
46
  [#1960]: https://github.com/sinatra/sinatra/pull/1960
26
- [#1975]: https://github.com/sinatra/sinatra/pull/1960
47
+ [#1975]: https://github.com/sinatra/sinatra/pull/1975
27
48
 
28
49
  ## 3.1.0 / 2023-08-07
29
50
 
data/Gemfile CHANGED
@@ -1,13 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Why use bundler?
4
- # Well, not all development dependencies install on all rubies. Moreover, `gem
5
- # install sinatra --development` doesn't work, as it will also try to install
6
- # development dependencies of our dependencies, and those are not conflict free.
7
- # So, here we are, `bundle install`.
8
- #
9
- # If you have issues with a gem: `bundle install --without-coffee-script`.
10
-
11
3
  source 'https://rubygems.org'
12
4
  gemspec
13
5
 
@@ -18,6 +10,13 @@ rack_version = nil if rack_version.empty? || (rack_version == 'stable')
18
10
  rack_version = { github: 'rack/rack' } if rack_version == 'head'
19
11
  gem 'rack', rack_version
20
12
 
13
+ rack_session_version = ENV['rack_session'].to_s
14
+ rack_session_version = nil if rack_session_version.empty? || (rack_session_version == 'stable')
15
+ rack_session_version = { github: 'rack/rack-session' } if rack_session_version == 'head'
16
+ gem 'rack-session', rack_session_version
17
+
18
+ gem 'rackup'
19
+
21
20
  puma_version = ENV['puma'].to_s
22
21
  puma_version = nil if puma_version.empty? || (puma_version == 'stable')
23
22
  puma_version = { github: 'puma/puma' } if puma_version == 'head'
@@ -31,15 +30,9 @@ gem 'yard' # used by rake doc
31
30
  gem 'rack-protection', path: 'rack-protection'
32
31
  gem 'sinatra-contrib', path: 'sinatra-contrib'
33
32
 
34
- # traces 0.10.0 started to use Ruby 2.7 syntax without specifying required Ruby version
35
- # https://github.com/socketry/traces/pull/8#discussion_r1237988182
36
- # async-http 0.60.2 added traces 0.10.0 as dependency
37
- # https://github.com/socketry/async-http/pull/124/files#r1237988899
38
- gem 'traces', '< 0.10.0' if RUBY_VERSION >= '2.6.0' && RUBY_VERSION < '2.7.0'
39
-
40
33
  gem 'asciidoctor'
41
34
  gem 'builder'
42
- gem 'childprocess'
35
+ gem 'childprocess', '>= 5'
43
36
  gem 'commonmarker', '~> 0.23.4', platforms: [:ruby]
44
37
  gem 'erubi'
45
38
  gem 'eventmachine'
@@ -47,25 +40,22 @@ gem 'falcon', '~> 0.40', platforms: [:ruby]
47
40
  gem 'haml', '~> 6'
48
41
  gem 'kramdown'
49
42
  gem 'liquid'
50
- # markaby 0.9.1 introduced Ruby 2.7 syntax in https://github.com/markaby/markaby/pull/44
51
- # and does not specify required_ruby_version
52
- if RUBY_VERSION >= '2.6.0' && RUBY_VERSION < '2.7.0'
53
- gem 'markaby', '< 0.9.1'
54
- else
55
- gem 'markaby'
56
- end
43
+ gem 'markaby'
57
44
  gem 'nokogiri', '> 1.5.0'
58
45
  gem 'pandoc-ruby', '~> 2.0.2'
59
46
  gem 'rabl'
60
- if RUBY_ENGINE == 'truffleruby'
61
- gem 'rdiscount', '< 2.2.7.2' # https://github.com/oracle/truffleruby/issues/3362
62
- else
63
- gem 'rdiscount', platforms: [:ruby]
64
- end
47
+ gem 'rdiscount', platforms: [:ruby]
65
48
  gem 'rdoc'
66
49
  gem 'redcarpet', platforms: [:ruby]
67
- gem 'sass-embedded', '~> 1.54'
68
50
  gem 'simplecov', require: false
69
51
  gem 'slim', '~> 4'
70
52
  gem 'yajl-ruby', platforms: [:ruby]
71
53
  gem 'zeitwerk'
54
+
55
+ # sass-embedded depends on google-protobuf
56
+ # which fails to be installed on JRuby and TruffleRuby under aarch64
57
+ # https://github.com/jruby/jruby/issues/8062
58
+ # https://github.com/protocolbuffers/protobuf/issues/11935
59
+ java = %w(jruby truffleruby).include?(RUBY_ENGINE)
60
+ aarch64 = RbConfig::CONFIG["target_cpu"] == 'aarch64'
61
+ gem 'sass-embedded', '~> 1.54' unless java && aarch64
data/README.md CHANGED
@@ -1922,7 +1922,7 @@ set :protection, :except => :path_traversal
1922
1922
  You can also hand in an array in order to disable a list of protections:
1923
1923
 
1924
1924
  ```ruby
1925
- set :protection, :except => [:path_traversal, :session_hijacking]
1925
+ set :protection, :except => [:path_traversal, :remote_token]
1926
1926
  ```
1927
1927
 
1928
1928
  By default, Sinatra will only set up session based protection if `:sessions`
@@ -2820,30 +2820,24 @@ uses a threaded model of concurrency.
2820
2820
 
2821
2821
  The following Ruby versions are officially supported:
2822
2822
  <dl>
2823
- <dt>Ruby 2.6</dt>
2823
+ <dt>Ruby</dt>
2824
2824
  <dd>
2825
- 2.6 is fully supported and recommended. There are currently no plans to
2826
- drop official support for it.
2825
+ <a href="https://www.ruby-lang.org/en/downloads/">The stable releases</a> are fully supported and recommended.
2827
2826
  </dd>
2828
2827
 
2829
- <dt>Rubinius</dt>
2828
+ <dt>TruffleRuby</dt>
2830
2829
  <dd>
2831
- Rubinius is officially supported (Rubinius >= 2.x). It is recommended to
2832
- <tt>gem install puma</tt>.
2830
+ The latest stable release of TruffleRuby is supported.
2833
2831
  </dd>
2834
2832
 
2835
2833
  <dt>JRuby</dt>
2836
2834
  <dd>
2837
- The latest stable release of JRuby is officially supported. It is not
2838
- recommended to use C extensions with JRuby. It is recommended to
2839
- <tt>gem install trinidad</tt>.
2835
+ The latest stable release of JRuby is supported. It is not
2836
+ recommended to use C extensions with JRuby.
2840
2837
  </dd>
2841
2838
  </dl>
2842
2839
 
2843
- Versions of Ruby before 2.6 are no longer supported as of Sinatra 3.0.0.
2844
-
2845
- We also keep an eye on upcoming Ruby versions. Expect upcoming
2846
- 3.x releases to be fully supported.
2840
+ Versions of Ruby before 2.7.8 are no longer supported as of Sinatra 4.0.0.
2847
2841
 
2848
2842
  Sinatra should work on any operating system supported by the chosen Ruby
2849
2843
  implementation.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.0
1
+ 4.0.0
data/lib/sinatra/base.rb CHANGED
@@ -2,8 +2,13 @@
2
2
 
3
3
  # external dependencies
4
4
  require 'rack'
5
+ begin
6
+ require 'rackup'
7
+ rescue LoadError
8
+ end
5
9
  require 'tilt'
6
10
  require 'rack/protection'
11
+ require 'rack/session'
7
12
  require 'mustermann'
8
13
  require 'mustermann/sinatra'
9
14
  require 'mustermann/regular'
@@ -176,8 +181,8 @@ module Sinatra
176
181
  result = body
177
182
 
178
183
  if drop_content_info?
179
- headers.delete 'Content-Length'
180
- headers.delete 'Content-Type'
184
+ headers.delete 'content-length'
185
+ headers.delete 'content-type'
181
186
  end
182
187
 
183
188
  if drop_body?
@@ -186,9 +191,9 @@ module Sinatra
186
191
  end
187
192
 
188
193
  if calculate_content_length?
189
- # if some other code has already set Content-Length, don't muck with it
194
+ # if some other code has already set content-length, don't muck with it
190
195
  # currently, this would be the static file-handler
191
- headers['Content-Length'] = body.map(&:bytesize).reduce(0, :+).to_s
196
+ headers['content-length'] = body.map(&:bytesize).reduce(0, :+).to_s
192
197
  end
193
198
 
194
199
  [status, headers, result]
@@ -197,7 +202,7 @@ module Sinatra
197
202
  private
198
203
 
199
204
  def calculate_content_length?
200
- headers['Content-Type'] && !headers['Content-Length'] && (Array === body)
205
+ headers['content-type'] && !headers['content-length'] && (Array === body)
201
206
  end
202
207
 
203
208
  def drop_content_info?
@@ -289,10 +294,8 @@ module Sinatra
289
294
  def block.each; yield(call) end
290
295
  response.body = block
291
296
  elsif value
292
- # Rack 2.0 returns a Rack::File::Iterator here instead of
293
- # Rack::File as it was in the previous API.
294
297
  unless request.head? || value.is_a?(Rack::Files::Iterator) || value.is_a?(Stream)
295
- headers.delete 'Content-Length'
298
+ headers.delete 'content-length'
296
299
  end
297
300
  response.body = value
298
301
  else
@@ -302,7 +305,10 @@ module Sinatra
302
305
 
303
306
  # Halt processing and redirect to the URI provided.
304
307
  def redirect(uri, *args)
305
- if (env['HTTP_VERSION'] == 'HTTP/1.1') && (env['REQUEST_METHOD'] != 'GET')
308
+ # SERVER_PROTOCOL is required in Rack 3, fall back to HTTP_VERSION
309
+ # for servers not updated for Rack 3 (like Puma 5)
310
+ http_version = env['SERVER_PROTOCOL'] || env['HTTP_VERSION']
311
+ if (http_version == 'HTTP/1.1') && (env['REQUEST_METHOD'] != 'GET')
306
312
  status 303
307
313
  else
308
314
  status 302
@@ -372,10 +378,10 @@ module Sinatra
372
378
  Base.mime_type(type)
373
379
  end
374
380
 
375
- # Set the Content-Type of the response body given a media type or file
381
+ # Set the content-type of the response body given a media type or file
376
382
  # extension.
377
383
  def content_type(type = nil, params = {})
378
- return response['Content-Type'] unless type
384
+ return response['content-type'] unless type
379
385
 
380
386
  default = params.delete :default
381
387
  mime_type = mime_type(type) || default
@@ -393,7 +399,7 @@ module Sinatra
393
399
  "#{key}=#{val}"
394
400
  end.join(', ')
395
401
  end
396
- response['Content-Type'] = mime_type
402
+ response['content-type'] = mime_type
397
403
  end
398
404
 
399
405
  # https://html.spec.whatwg.org/#multipart-form-data
@@ -412,12 +418,12 @@ module Sinatra
412
418
  params = format('; filename="%s"', File.basename(filename).gsub(/["\r\n]/, MULTIPART_FORM_DATA_REPLACEMENT_TABLE))
413
419
  response['Content-Disposition'] << params
414
420
  ext = File.extname(filename)
415
- content_type(ext) unless response['Content-Type'] || ext.empty?
421
+ content_type(ext) unless response['content-type'] || ext.empty?
416
422
  end
417
423
 
418
424
  # Use the contents of the file at +path+ as the response body.
419
425
  def send_file(path, opts = {})
420
- if opts[:type] || !response['Content-Type']
426
+ if opts[:type] || !response['content-type']
421
427
  content_type opts[:type] || File.extname(path), default: 'application/octet-stream'
422
428
  end
423
429
 
@@ -433,7 +439,7 @@ module Sinatra
433
439
  result = file.serving(request, path)
434
440
 
435
441
  result[1].each { |k, v| headers[k] ||= v }
436
- headers['Content-Length'] = result[1]['Content-Length']
442
+ headers['content-length'] = result[1]['content-length']
437
443
  opts[:status] &&= Integer(opts[:status])
438
444
  halt (opts[:status] || result[0]), result[2]
439
445
  rescue Errno::ENOENT
@@ -995,7 +1001,7 @@ module Sinatra
995
1001
  invoke { dispatch! }
996
1002
  invoke { error_block!(response.status) } unless @env['sinatra.error']
997
1003
 
998
- unless @response['Content-Type']
1004
+ unless @response['content-type']
999
1005
  if Array === body && body[0].respond_to?(:content_type)
1000
1006
  content_type body[0].content_type
1001
1007
  elsif (default = settings.default_content_type)
@@ -1058,7 +1064,7 @@ module Sinatra
1058
1064
  routes = base.routes[@request.request_method]
1059
1065
 
1060
1066
  routes&.each do |pattern, conditions, block|
1061
- response.delete_header('Content-Type') unless @pinned_response
1067
+ response.delete_header('content-type') unless @pinned_response
1062
1068
 
1063
1069
  returned_pass_block = process_route(pattern, conditions) do |*args|
1064
1070
  env['sinatra.route'] = "#{@request.request_method} #{pattern}"
@@ -1179,7 +1185,7 @@ module Sinatra
1179
1185
  invoke do
1180
1186
  static! if settings.static? && (request.get? || request.head?)
1181
1187
  filter! :before do
1182
- @pinned_response = !response['Content-Type'].nil?
1188
+ @pinned_response = !response['content-type'].nil?
1183
1189
  end
1184
1190
  route!
1185
1191
  end
@@ -1460,7 +1466,13 @@ module Sinatra
1460
1466
  # mime_types :js # => ['application/javascript', 'text/javascript']
1461
1467
  def mime_types(type)
1462
1468
  type = mime_type type
1463
- type =~ %r{^application/(xml|javascript)$} ? [type, "text/#{$1}"] : [type]
1469
+ if type =~ %r{^application/(xml|javascript)$}
1470
+ [type, "text/#{$1}"]
1471
+ elsif type =~ %r{^text/(xml|javascript)$}
1472
+ [type, "application/#{$1}"]
1473
+ else
1474
+ [type]
1475
+ end
1464
1476
  end
1465
1477
 
1466
1478
  # Define a before filter; runs before all requests within the same
@@ -1589,10 +1601,27 @@ module Sinatra
1589
1601
  # Puma, Falcon, or WEBrick (in that order). If given a block, will call
1590
1602
  # with the constructed handler once we have taken the stage.
1591
1603
  def run!(options = {}, &block)
1604
+ unless defined?(Rackup::Handler)
1605
+ rackup_warning = <<~MISSING_RACKUP
1606
+ Sinatra could not start, the "rackup" gem was not found!
1607
+
1608
+ Add it to your bundle with:
1609
+
1610
+ bundle add rackup
1611
+
1612
+ or install it with:
1613
+
1614
+ gem install rackup
1615
+
1616
+ MISSING_RACKUP
1617
+ warn rackup_warning
1618
+ exit 1
1619
+ end
1620
+
1592
1621
  return if running?
1593
1622
 
1594
1623
  set options
1595
- handler = Rack::Handler.pick(server)
1624
+ handler = Rackup::Handler.pick(server)
1596
1625
  handler_name = handler.name.gsub(/.*::/, '')
1597
1626
  server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {}
1598
1627
  server_settings.merge!(Port: port, Host: bind)
@@ -1724,7 +1753,7 @@ module Sinatra
1724
1753
  types.map! { |t| mime_types(t) }
1725
1754
  types.flatten!
1726
1755
  condition do
1727
- response_content_type = response['Content-Type']
1756
+ response_content_type = response['content-type']
1728
1757
  preferred_type = request.preferred_type(types)
1729
1758
 
1730
1759
  if response_content_type
@@ -1901,7 +1930,7 @@ module Sinatra
1901
1930
  set :dump_errors, proc { !test? }
1902
1931
  set :show_exceptions, proc { development? }
1903
1932
  set :sessions, false
1904
- set :session_store, Rack::Protection::EncryptedCookie
1933
+ set :session_store, Rack::Session::Cookie
1905
1934
  set :logging, false
1906
1935
  set :protection, true
1907
1936
  set :method_override, false
@@ -43,12 +43,6 @@ module Sinatra
43
43
  new.merge!(Hash[*args])
44
44
  end
45
45
 
46
- def initialize(*args)
47
- args.map!(&method(:convert_value))
48
-
49
- super(*args)
50
- end
51
-
52
46
  def default(*args)
53
47
  args.map!(&method(:convert_key))
54
48
 
@@ -38,8 +38,8 @@ module Sinatra
38
38
  [
39
39
  500,
40
40
  {
41
- 'Content-Type' => content_type,
42
- 'Content-Length' => body.bytesize.to_s
41
+ 'content-type' => content_type,
42
+ 'content-length' => body.bytesize.to_s
43
43
  },
44
44
  [body]
45
45
  ]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sinatra
4
- VERSION = '3.2.0'
4
+ VERSION = '4.0.0'
5
5
  end
data/sinatra.gemspec CHANGED
@@ -43,10 +43,11 @@ RubyGems 2.0 or newer is required to protect against public gem pushes. You can
43
43
  'documentation_uri' => 'https://www.rubydoc.info/gems/sinatra'
44
44
  }
45
45
 
46
- s.required_ruby_version = '>= 2.6.0'
46
+ s.required_ruby_version = '>= 2.7.8'
47
47
 
48
48
  s.add_dependency 'mustermann', '~> 3.0'
49
- s.add_dependency 'rack', '~> 2.2', '>= 2.2.4'
49
+ s.add_dependency 'rack', '>= 3.0.0', '< 4'
50
+ s.add_dependency 'rack-session', '>= 2.0.0', '< 3'
50
51
  s.add_dependency 'rack-protection', version
51
52
  s.add_dependency 'tilt', '~> 2.0'
52
53
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Mizerany
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-12-29 00:00:00.000000000 Z
14
+ date: 2024-01-19 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: mustermann
@@ -31,36 +31,56 @@ dependencies:
31
31
  name: rack
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
- - - "~>"
35
- - !ruby/object:Gem::Version
36
- version: '2.2'
37
34
  - - ">="
38
35
  - !ruby/object:Gem::Version
39
- version: 2.2.4
36
+ version: 3.0.0
37
+ - - "<"
38
+ - !ruby/object:Gem::Version
39
+ version: '4'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '2.2'
46
+ version: 3.0.0
47
+ - - "<"
48
+ - !ruby/object:Gem::Version
49
+ version: '4'
50
+ - !ruby/object:Gem::Dependency
51
+ name: rack-session
52
+ requirement: !ruby/object:Gem::Requirement
53
+ requirements:
47
54
  - - ">="
48
55
  - !ruby/object:Gem::Version
49
- version: 2.2.4
56
+ version: 2.0.0
57
+ - - "<"
58
+ - !ruby/object:Gem::Version
59
+ version: '3'
60
+ type: :runtime
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 2.0.0
67
+ - - "<"
68
+ - !ruby/object:Gem::Version
69
+ version: '3'
50
70
  - !ruby/object:Gem::Dependency
51
71
  name: rack-protection
52
72
  requirement: !ruby/object:Gem::Requirement
53
73
  requirements:
54
74
  - - '='
55
75
  - !ruby/object:Gem::Version
56
- version: 3.2.0
76
+ version: 4.0.0
57
77
  type: :runtime
58
78
  prerelease: false
59
79
  version_requirements: !ruby/object:Gem::Requirement
60
80
  requirements:
61
81
  - - '='
62
82
  - !ruby/object:Gem::Version
63
- version: 3.2.0
83
+ version: 4.0.0
64
84
  - !ruby/object:Gem::Dependency
65
85
  name: tilt
66
86
  requirement: !ruby/object:Gem::Requirement
@@ -132,7 +152,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
152
  requirements:
133
153
  - - ">="
134
154
  - !ruby/object:Gem::Version
135
- version: 2.6.0
155
+ version: 2.7.8
136
156
  required_rubygems_version: !ruby/object:Gem::Requirement
137
157
  requirements:
138
158
  - - ">="