frise 0.3.0.pre → 0.3.0

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: 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