frise 0.3.0.pre → 0.3.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: 72db98e097cb7abccf1a1208a53efa9a2486d49d3f58422a70e6f32ac7cbb2a8
4
- data.tar.gz: 52f15d4c10262d54dc7534fa35c16abb66ad33d0498ceff612cc78124154fcf4
3
+ metadata.gz: 5923c848338d6a2f7dfc35211200ab51a789ad9e9967742e4eb57430346785e9
4
+ data.tar.gz: e08f1fdf3a14fe288ad67a0baa6a9e557294de9ac5ea814426e9b92792b1be95
5
5
  SHA512:
6
- metadata.gz: 75b318b997eb2ab66dada979b270e468430ca372982d035bba4de12a68a0622f6897d928e173b67d7e046be2ecdee0d7b1374e0a0d50da55e80354d60285eb9f
7
- data.tar.gz: b25a7625181eaf4d90f202ca0aa9dc9095ada98318272c2d5c999beb8ea28e0e7af397b1612692bd18709a59dca4cab758d30ee515563806d6def511500243e7
6
+ metadata.gz: a578f2042b86832986bed1cecbe435330e509e2f6f166ff7302c3eeca37e445bc7acbbcbd4fe16d3cf9c23be68603cd9d4e13f17c508edaeff5e96169b41eaa9
7
+ data.tar.gz: 1c4378dcec5e8738f25248d6a45fcc96b4392f7144995e08d57407abd3bf1ad5bfe506fe6e1117aa4caef7900dcedfba9dc8b4267b1c4cd6d273c5395313cd2f
@@ -1,11 +1,26 @@
1
+ ### 0.3.0 (April 16, 2018)
2
+
3
+ - Breaking changes
4
+ - Defaults and schemas are now defined using a directive in the YAML configs instead of
5
+ implicitly by looking at load paths. See ([#7](https://github.com/velocidi/frise/pull/7)) for
6
+ more information on migration;
7
+ - New features
8
+ - `$include` and `$schema` directives are now available in config files, allowing users to
9
+ validate and include defaults at any part of the config
10
+ ([#7](https://github.com/velocidi/frise/pull/7));
11
+ - A new `$content_include` directive allows users to include the content of a file as a YAML
12
+ string ([#8](https://github.com/velocidi/frise/pull/8));
13
+ - The `_file_dir` Liquid variable is now available in all included files, containing always the
14
+ absolute path to the file being loaded ([#7](https://github.com/velocidi/frise/pull/7)).
15
+
1
16
  ### 0.2.0 (August 17, 2017)
2
17
 
3
18
  - New features
4
19
  - New schema types `$enum` and `$one_of` for specifying enumerations and values with multiple
5
- possible schemas ([#5](https://github.com/ShiftForward/frise/pull/5)).
20
+ possible schemas ([#5](https://github.com/velocidi/frise/pull/5)).
6
21
  - Bug fixes
7
22
  - Deal correctly with non-existing schema files in the load path
8
- ([#4](https://github.com/ShiftForward/frise/pull/4)).
23
+ ([#4](https://github.com/velocidi/frise/pull/4)).
9
24
 
10
25
  ### 0.1.0 (August 10, 2017)
11
26
 
data/README.md CHANGED
@@ -1,12 +1,13 @@
1
1
  # Frise
2
- [![Build Status](https://travis-ci.org/ShiftForward/frise.svg?branch=master)](https://travis-ci.org/ShiftForward/frise)
3
- [![Coverage Status](https://coveralls.io/repos/github/ShiftForward/frise/badge.svg?branch=master)](https://coveralls.io/github/ShiftForward/frise?branch=master)
2
+ [![Build Status](https://travis-ci.org/velocidi/frise.svg?branch=master)](https://travis-ci.org/velocidi/frise)
3
+ [![Coverage Status](https://coveralls.io/repos/github/velocidi/frise/badge.svg?branch=master)](https://coveralls.io/github/velocidi/frise?branch=master)
4
4
  [![Gem Version](https://badge.fury.io/rb/frise.svg)](https://badge.fury.io/rb/frise)
5
5
 
6
6
  Frise is a library for loading configuration files as native Ruby structures. Besides reading and
7
7
  parsing the files themselves, it also:
8
8
 
9
- - Completes it with default values specified in another file or set of files;
9
+ - Allows defining other files to be merged anywhere in the config, which can be used to provide default values specified
10
+ in another file or set of files;
10
11
  - Interprets [Liquid](https://shopify.github.io/liquid) templates in configs and defaults;
11
12
  - Validates the loaded config according to a schema file or set of files.
12
13
 
@@ -24,7 +25,6 @@ The simplest example would be to load [a simple configuration](example/config.ym
24
25
 
25
26
  ```ruby
26
27
  require 'frise'
27
- require 'pp'
28
28
 
29
29
  loader = Frise::Loader.new
30
30
  loader.load('example/config.yml')
@@ -44,12 +44,11 @@ Currently Frise only supports YAML files, but it may support JSON and other form
44
44
 
45
45
  ### Default values
46
46
 
47
- By defining directories where the files with default values can be found (in this example,
48
- [example/_defaults](example/_defaults)), Frise can handle its application internally on load time:
47
+ By using the `$include` directive pointing to the files where default values can be found (in this example,
48
+ [example/_defaults/config.yml](example/_defaults/config.yml)), Frise can handle its application internally on load time:
49
49
 
50
50
  ```ruby
51
- loader = Frise::Loader.new(defaults_load_paths: ['example/_defaults'])
52
- loader.load('example/config.yml')
51
+ loader.load('example/config_with_defaults.yml')
53
52
  # => {"movies"=>
54
53
  # [{"title"=>"The Shawshank Redemption",
55
54
  # "year"=>1994,
@@ -75,15 +74,11 @@ config.
75
74
  ### Schemas
76
75
 
77
76
  Additionally, configuration files can also be validated against a schema. By specifying
78
- `schema_load_paths`, users can provide directories where schema files such as
79
- [example/_schemas/config.yml](example/_schemas/config.yml) can be found:
77
+ `$schema` in the config, users can provide schema files such as
78
+ [example/_schemas/config.yml](example/_schemas/config.yml):
80
79
 
81
80
  ```ruby
82
- loader = Frise::Loader.new(
83
- schema_load_paths: ['example/_schemas'],
84
- defaults_load_paths: ['example/_defaults'])
85
-
86
- loader.load('example/config.yml')
81
+ loader.load('example/config_with_defaults_and_schema.yml')
87
82
  # {"movies"=>
88
83
  # [{"title"=>"The Shawshank Redemption",
89
84
  # "year"=>1994,
@@ -106,16 +101,14 @@ missing and Frise by default prints a summary of the errors and terminates the p
106
101
 
107
102
 
108
103
  ```ruby
109
- loader = Frise::Loader.new(schema_load_paths: ['example/_schemas'])
110
-
111
- loader.load('example/config.yml')
104
+ loader.load('example/config_with_schema.yml')
112
105
  # 2 config error(s) found:
113
106
  # - At movies.0.director: missing required value
114
107
  # - At ui: missing required value
115
108
  ```
116
109
 
117
110
  Once more, the structure of the schema mimics the structure of the config itself, making it easy to
118
- write schemas and to create a config scaffold from its schema later.
111
+ write schemas first and create a config scaffold from its schema later.
119
112
 
120
113
  Users can check a whole range of properties in config values besides their type: optional values,
121
114
  hashes with validated keys, hashes with unknown keys and even custom validations are also supported.
@@ -20,12 +20,12 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ['lib']
21
21
  spec.required_ruby_version = '>= 2.3.0'
22
22
 
23
- spec.add_dependency 'liquid', '~> 3.0'
23
+ spec.add_dependency 'liquid', '~> 4.0'
24
24
 
25
25
  spec.add_development_dependency 'bundler', '~> 1.14'
26
26
  spec.add_development_dependency 'coveralls', '~> 0.8.21'
27
27
  spec.add_development_dependency 'rake', '~> 12.3'
28
28
  spec.add_development_dependency 'rspec', '~> 3.4'
29
- spec.add_development_dependency 'rubocop', '~> 0.53.0'
29
+ spec.add_development_dependency 'rubocop', '0.55.0'
30
30
  spec.add_development_dependency 'simplecov', '~> 0.14.1'
31
31
  end
@@ -7,67 +7,75 @@ module Frise
7
7
  #
8
8
  # The merge_defaults and merge_defaults_at entrypoint methods provide ways to read files with
9
9
  # defaults and apply them to configuration objects.
10
- module DefaultsLoader
11
- class << self
12
- SYMBOLS = %w[$all $optional].freeze
10
+ class DefaultsLoader
11
+ SYMBOLS = %w[$all $optional].freeze
13
12
 
14
- def widened_class(obj)
15
- class_name = obj.class.to_s
16
- return 'Boolean' if %w[TrueClass FalseClass].include? class_name
17
- return 'Integer' if %w[Fixnum Bignum].include? class_name
18
- class_name
19
- end
13
+ def initialize(include_sym: '$include', content_include_sym: '$content_include', schema_sym: '$schema')
14
+ @include_sym = include_sym
15
+ @content_include_sym = content_include_sym
16
+ @schema_sym = schema_sym
17
+ end
20
18
 
21
- def merge_defaults_obj(config, defaults)
22
- if defaults.nil?
23
- config
19
+ def widened_class(obj)
20
+ class_name = obj.class.to_s
21
+ return 'String' if class_name == 'Hash' && !obj[@content_include_sym].nil?
22
+ return 'Boolean' if %w[TrueClass FalseClass].include? class_name
23
+ return 'Integer' if %w[Fixnum Bignum].include? class_name
24
+ class_name
25
+ end
24
26
 
25
- elsif config.nil?
26
- if defaults.class != Hash then defaults
27
- elsif defaults['$optional'] then nil
28
- else merge_defaults_obj({}, defaults)
29
- end
27
+ def merge_defaults_obj(config, defaults)
28
+ config_class = widened_class(config)
29
+ defaults_class = widened_class(defaults)
30
30
 
31
- elsif defaults.class == Array && config.class == Array
32
- defaults + config
31
+ if defaults.nil?
32
+ config
33
33
 
34
- elsif defaults.class == Hash && defaults['$all'] && config.class == Array
35
- config.map { |elem| merge_defaults_obj(elem, defaults['$all']) }
34
+ elsif config.nil?
35
+ if defaults_class != 'Hash' then defaults
36
+ elsif defaults['$optional'] then nil
37
+ else merge_defaults_obj({}, defaults)
38
+ end
36
39
 
37
- elsif defaults.class == Hash && config.class == Hash
38
- new_config = {}
39
- (config.keys + defaults.keys).uniq.each do |key|
40
- next if SYMBOLS.include?(key)
41
- new_config[key] = config[key]
42
- new_config[key] = merge_defaults_obj(new_config[key], defaults[key]) if defaults.key?(key)
43
- new_config[key] = merge_defaults_obj(new_config[key], defaults['$all']) unless new_config[key].nil?
44
- new_config.delete(key) if new_config[key].nil?
45
- end
46
- new_config
40
+ elsif defaults_class == 'Array' && config_class == 'Array'
41
+ defaults + config
47
42
 
48
- elsif widened_class(defaults) != widened_class(config)
49
- raise "Cannot merge config #{config.inspect} (#{widened_class(config)}) " \
50
- "with default #{defaults.inspect} (#{widened_class(defaults)})"
43
+ elsif defaults_class == 'Hash' && defaults['$all'] && config_class == 'Array'
44
+ config.map { |elem| merge_defaults_obj(elem, defaults['$all']) }
51
45
 
52
- else
53
- config
46
+ elsif defaults_class == 'Hash' && config_class == 'Hash'
47
+ new_config = {}
48
+ (config.keys + defaults.keys).uniq.each do |key|
49
+ next if SYMBOLS.include?(key)
50
+ new_config[key] = config[key]
51
+ new_config[key] = merge_defaults_obj(new_config[key], defaults[key]) if defaults.key?(key)
52
+ new_config[key] = merge_defaults_obj(new_config[key], defaults['$all']) unless new_config[key].nil?
53
+ new_config.delete(key) if new_config[key].nil?
54
54
  end
55
- end
55
+ new_config
56
56
 
57
- def merge_defaults_obj_at(config, at_path, defaults)
58
- at_path.reverse.each { |key| defaults = { key => defaults } }
59
- merge_defaults_obj(config, defaults)
60
- end
57
+ elsif defaults_class != config_class
58
+ raise "Cannot merge config #{config.inspect} (#{widened_class(config)}) " \
59
+ "with default #{defaults.inspect} (#{widened_class(defaults)})"
61
60
 
62
- def merge_defaults(config, defaults_file, symbol_table = config)
63
- defaults = Parser.parse(defaults_file, symbol_table) || {}
64
- merge_defaults_obj(config, defaults)
61
+ else
62
+ config
65
63
  end
64
+ end
66
65
 
67
- def merge_defaults_at(config, at_path, defaults_file, symbol_table = config)
68
- defaults = Parser.parse(defaults_file, symbol_table) || {}
69
- merge_defaults_obj_at(config, at_path, defaults)
70
- end
66
+ def merge_defaults_obj_at(config, at_path, defaults)
67
+ at_path.reverse.each { |key| defaults = { key => defaults } }
68
+ merge_defaults_obj(config, defaults)
69
+ end
70
+
71
+ def merge_defaults(config, defaults_file, symbol_table = config)
72
+ defaults = Parser.parse(defaults_file, symbol_table) || {}
73
+ merge_defaults_obj(config, defaults)
74
+ end
75
+
76
+ def merge_defaults_at(config, at_path, defaults_file, symbol_table = config)
77
+ defaults = Parser.parse(defaults_file, symbol_table) || {}
78
+ merge_defaults_obj_at(config, at_path, defaults)
71
79
  end
72
80
  end
73
81
  end
@@ -10,12 +10,25 @@ module Frise
10
10
  #
11
11
  # The load method loads a configuration file, merges the applicable includes and validates its schema.
12
12
  class Loader
13
- def initialize(include_sym: '$include', schema_sym: '$schema', pre_loaders: [], validators: nil, exit_on_fail: true)
13
+ def initialize(include_sym: '$include',
14
+ content_include_sym: '$content_include',
15
+ schema_sym: '$schema',
16
+ pre_loaders: [],
17
+ validators: nil,
18
+ exit_on_fail: true)
19
+
14
20
  @include_sym = include_sym
21
+ @content_include_sym = content_include_sym
15
22
  @schema_sym = schema_sym
16
23
  @pre_loaders = pre_loaders
17
24
  @validators = validators
18
25
  @exit_on_fail = exit_on_fail
26
+
27
+ @defaults_loader = DefaultsLoader.new(
28
+ include_sym: include_sym,
29
+ content_include_sym: content_include_sym,
30
+ schema_sym: schema_sym
31
+ )
19
32
  end
20
33
 
21
34
  def load(config_file, global_vars = {})
@@ -36,35 +49,49 @@ module Frise
36
49
  def process_includes(config, at_path, root_config, global_vars)
37
50
  return config unless config.class == Hash
38
51
 
39
- config, defaults_confs = extract_include(config)
40
- if defaults_confs.empty?
52
+ # process $content_include directives
53
+ config, content_include_confs = extract_content_include(config, at_path)
54
+ unless content_include_confs.empty?
55
+ raise "At #{build_path(at_path)}: a #{@content_include_sym} must not have any sibling key" unless config.empty?
56
+
57
+ content = ''
58
+ content_include_confs.each do |include_conf|
59
+ symbol_table = build_symbol_table(root_config, at_path, nil, global_vars, include_conf)
60
+ content += Parser.parse_as_text(include_conf['file'], symbol_table) || ''
61
+ end
62
+ return content
63
+ end
64
+
65
+ # process $include directives
66
+ config, include_confs = extract_include(config, at_path)
67
+ if include_confs.empty?
41
68
  config.map { |k, v| [k, process_includes(v, at_path + [k], root_config, global_vars)] }.to_h
42
69
  else
43
70
  Lazy.new do
44
- defaults_confs.each do |defaults_conf|
45
- extra_vars = (defaults_conf['vars'] || {}).map { |k, v| [k, root_config.dig(*v.split('.'))] }.to_h
46
- extra_consts = defaults_conf['constants'] || {}
47
- symbol_table = merge_at(root_config, at_path, config)
48
- .merge(global_vars).merge(extra_vars).merge(extra_consts).merge('_this' => config)
71
+ include_confs.each do |include_conf|
72
+ symbol_table = build_symbol_table(root_config, at_path, config, global_vars, include_conf)
73
+ included_config = Parser.parse(include_conf['file'], symbol_table)
49
74
 
50
- config = DefaultsLoader.merge_defaults_obj(config, Parser.parse(defaults_conf['file'], symbol_table))
75
+ config = @defaults_loader.merge_defaults_obj(config, included_config)
76
+ config = process_includes(config, at_path, merge_at(root_config, at_path, config), global_vars)
51
77
  end
52
- process_includes(config, at_path, merge_at(root_config, at_path, config), global_vars)
78
+ updated_root_config = merge_at(root_config, at_path, config)
79
+ config.map { |k, v| [k, process_includes(v, at_path + [k], updated_root_config, global_vars)] }.to_h
53
80
  end
54
81
  end
55
82
  end
56
83
 
57
- def process_schema_includes(schema, global_vars)
84
+ def process_schema_includes(schema, at_path, global_vars)
58
85
  return schema unless schema.class == Hash
59
86
 
60
- schema, included_schemas = extract_include(schema)
87
+ schema, included_schemas = extract_include(schema, at_path)
61
88
  if included_schemas.empty?
62
- schema.map { |k, v| [k, process_schema_includes(v, global_vars)] }.to_h
89
+ schema.map { |k, v| [k, process_schema_includes(v, at_path + [k], global_vars)] }.to_h
63
90
  else
64
91
  included_schemas.each do |defaults_conf|
65
92
  schema = Parser.parse(defaults_conf['file'], global_vars).merge(schema)
66
93
  end
67
- process_schema_includes(schema, global_vars)
94
+ process_schema_includes(schema, at_path, global_vars)
68
95
  end
69
96
  end
70
97
 
@@ -77,10 +104,10 @@ module Frise
77
104
  [k, new_v]
78
105
  end.to_h
79
106
 
80
- config, schema_files = extract_schema(config)
107
+ config, schema_files = extract_schema(config, at_path)
81
108
  schema_files.each do |schema_file|
82
109
  schema = Parser.parse(schema_file, global_vars)
83
- schema = process_schema_includes(schema, global_vars)
110
+ schema = process_schema_includes(schema, at_path, global_vars)
84
111
 
85
112
  errors = Validator.validate_obj(config,
86
113
  schema,
@@ -93,37 +120,68 @@ module Frise
93
120
  config
94
121
  end
95
122
 
96
- def extract_schema(config)
97
- extract_special(config, @schema_sym) do |value|
123
+ def extract_schema(config, at_path)
124
+ extract_special(config, @schema_sym, at_path) do |value|
98
125
  case value
99
126
  when String then value
100
- else raise "Illegal value for a #{@schema_sym} element: #{value.inspect}"
127
+ else raise "At #{build_path(at_path)}: illegal value for a #{@schema_sym} element: #{value.inspect}"
101
128
  end
102
129
  end
103
130
  end
104
131
 
105
- def extract_include(config)
106
- extract_special(config, @include_sym) do |value|
132
+ def extract_include(config, at_path)
133
+ extract_include_base(config, @include_sym, at_path)
134
+ end
135
+
136
+ def extract_content_include(config, at_path)
137
+ extract_include_base(config, @content_include_sym, at_path)
138
+ end
139
+
140
+ def extract_include_base(config, sym, at_path)
141
+ extract_special(config, sym, at_path) do |value|
107
142
  case value
108
143
  when Hash then value
109
144
  when String then { 'file' => value }
110
- else raise "Illegal value for a #{@include_sym} element: #{value.inspect}"
145
+ else raise "At #{build_path(at_path)}: illegal value for a #{sym} element: #{value.inspect}"
111
146
  end
112
147
  end
113
148
  end
114
149
 
115
- def extract_special(config, key)
150
+ def extract_special(config, key, at_path)
116
151
  case config[key]
117
152
  when nil then [config, []]
118
153
  when Array then [config.reject { |k| k == key }, config[key].map { |e| yield e }]
119
- else raise "Illegal value for #{key}: #{config[key].inspect}"
154
+ else raise "At #{build_path(at_path)}: illegal value for #{key}: #{config[key].inspect}"
120
155
  end
121
156
  end
122
157
 
158
+ # merges the `to_merge` value on `config` at path `at_path`
123
159
  def merge_at(config, at_path, to_merge)
124
160
  return config.merge(to_merge) if at_path.empty?
125
161
  head, *tail = at_path
126
162
  config.merge(head => merge_at(config[head], tail, to_merge))
127
163
  end
164
+
165
+ # builds the symbol table for the Liquid renderization of a file, based on:
166
+ # - `root_config`: the root of the whole config
167
+ # - `at_path`: the current path
168
+ # - `config`: the config subtree being built
169
+ # - `global_vars`: the global variables
170
+ # - `include_conf`: the $include or $content_include configuration
171
+ def build_symbol_table(root_config, at_path, config, global_vars, include_conf)
172
+ extra_vars = (include_conf['vars'] || {}).map { |k, v| [k, root_config.dig(*v.split('.'))] }.to_h
173
+ extra_consts = include_conf['constants'] || {}
174
+
175
+ (config ? merge_at(root_config, at_path, config) : root_config)
176
+ .merge(global_vars)
177
+ .merge(extra_vars)
178
+ .merge(extra_consts)
179
+ .merge('_this' => config)
180
+ end
181
+
182
+ # builds a user-friendly string indicating a path
183
+ def build_path(at_path)
184
+ at_path.empty? ? '<root>' : at_path.join('.')
185
+ end
128
186
  end
129
187
  end
@@ -10,15 +10,20 @@ module Frise
10
10
  class << self
11
11
  def parse(file, symbol_table = nil)
12
12
  return nil unless File.file? file
13
- content = File.open(file).read
13
+ YAML.safe_load(parse_as_text(file, symbol_table), [], [], true) || {}
14
+ end
15
+
16
+ def parse_as_text(file, symbol_table = nil)
17
+ return nil unless File.file? file
18
+ content = File.read(file)
14
19
  content = Liquid::Template.parse(content).render with_internal_vars(file, symbol_table) if symbol_table
15
- YAML.safe_load(content, [], [], true) || {}
20
+ content
16
21
  end
17
22
 
18
23
  private
19
24
 
20
25
  def with_internal_vars(file, symbol_table)
21
- symbol_table.merge('_file_dir' => File.dirname(file))
26
+ symbol_table.merge('_file_dir' => File.expand_path(File.dirname(file)))
22
27
  end
23
28
  end
24
29
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Frise
4
- VERSION = '0.3.0.pre'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.pre
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ShiftForward
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-02 00:00:00.000000000 Z
11
+ date: 2018-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
19
+ version: '4.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '3.0'
26
+ version: '4.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 0.53.0
89
+ version: 0.55.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 0.53.0
96
+ version: 0.55.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -147,9 +147,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
147
147
  version: 2.3.0
148
148
  required_rubygems_version: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ">"
150
+ - - ">="
151
151
  - !ruby/object:Gem::Version
152
- version: 1.3.1
152
+ version: '0'
153
153
  requirements: []
154
154
  rubyforge_project:
155
155
  rubygems_version: 2.7.6